diff --git a/README.md b/README.md index 81ccc900797..0bcba5911d4 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # HtmlUnit -Version 4.2.0 / June 05, 2024 +Version 4.3.0 / June 27, 2024 :heart: [Sponsor](https://github.com/sponsors/rbri) @@ -49,7 +49,7 @@ Add to your `pom.xml`: org.htmlunit htmlunit - 4.2.0 + 4.3.0 ``` @@ -58,7 +58,7 @@ Add to your `pom.xml`: Add to your `build.gradle`: ```groovy -implementation group: 'org.htmlunit', name: 'htmlunit', version: '4.2.0' +implementation group: 'org.htmlunit', name: 'htmlunit', version: '4.3.0' ``` ## Vulnerabilities @@ -132,7 +132,7 @@ Add the snapshot repository and dependency to your `pom.xml`: org.htmlunit htmlunit - 4.3.0-SNAPSHOT + 4.4.0-SNAPSHOT @@ -151,7 +151,7 @@ repositories { } // ... dependencies { - implementation group: 'org.htmlunit', name: 'htmlunit', version: '4.2.0-SNAPSHOT' + implementation group: 'org.htmlunit', name: 'htmlunit', version: '4.4.0-SNAPSHOT' // ... } ``` diff --git a/pom.xml b/pom.xml index f1263245e29..a3443fcd38b 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 org.htmlunit htmlunit - 4.2.0 + 4.3.0 HtmlUnit Gargoyle Software Inc. @@ -25,17 +25,17 @@ 8 8 - 4.2.0 - 4.2.0 - 4.2.1 - 4.2.0 - 4.2.0 - 4.2.0 + 4.3.0 + 4.3.0 + 4.3.0 + 4.3.0 + 4.3.0 + 4.3.0 4.5.14 - 4.21.0 - 4.21.0 + 4.22.0 + 4.22.0 9.4.54.v20240208 2.23.1 @@ -43,7 +43,7 @@ 10.17.0 - 4.8.5 + 4.8.6 6.55.0 4.13.2 1.3.0 @@ -65,7 +65,7 @@ org.apache.maven.plugins maven-checkstyle-plugin - 3.3.1 + 3.4.0 checkstyle.xml checkstyle_suppressions.xml @@ -119,7 +119,7 @@ org.apache.maven.plugins maven-jar-plugin - 3.4.1 + 3.4.2 @@ -183,7 +183,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.5 + 3.3.0 org.apache.maven.plugins @@ -298,7 +298,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.5 + 3.3.0 false @@ -328,7 +328,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.5 + 3.3.0 false @@ -359,7 +359,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.5 + 3.3.0 false @@ -387,7 +387,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.5 + 3.3.0 false @@ -415,7 +415,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.5 + 3.3.0 false @@ -445,7 +445,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.5 + 3.3.0 false @@ -474,7 +474,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.5 + 3.3.0 false @@ -503,7 +503,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.5 + 3.3.0 false @@ -532,7 +532,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.5 + 3.3.0 false @@ -560,7 +560,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.5 + 3.3.0 false @@ -588,7 +588,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.5 + 3.3.0 false @@ -616,7 +616,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.5 + 3.3.0 false @@ -645,7 +645,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.5 + 3.3.0 false @@ -686,7 +686,7 @@ org.apache.maven.plugins maven-project-info-reports-plugin - 3.5.0 + 3.6.0 org.apache.maven.plugins @@ -1257,7 +1257,7 @@ commons-net commons-net - 3.11.0 + 3.11.1 commons-codec @@ -1321,7 +1321,7 @@ com.twelvemonkeys.imageio imageio-batik - 3.10.1 + 3.11.0 test @@ -1376,7 +1376,7 @@ org.jfree jfreechart - 1.5.4 + 1.5.5 test @@ -1437,17 +1437,25 @@ ${selenium.version} test + + org.seleniumhq.selenium + selenium-devtools-v126 + ${selenium.version} + test + + - sonatype-nexus-snapshots + s01-sonatype-nexus-snapshots https://s01.oss.sonatype.org/content/repositories/snapshots - sonatype-nexus-staging + s01-sonatype-nexus-staging https://s01.oss.sonatype.org/service/local/staging/deploy/maven2 + diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 0b124c8fc42..3b8ff3f3431 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -7,6 +7,71 @@ + + + Improved implementation of the hidden attribute setter. + + + core-js: another hack on the const handling (in most cases const no treated like let - this is not correct + but avoids the 'constant redefinition' parser error). + + + Sarissa 0.9.9.7 tests added. + + + DateTimeFormat.format now takes care of the current browser timezone and locale. + + + Fix some NPE in HtmlSerializer's. + + + Improved innerHTML content parsing for special tags like title, textarea, style, and script. + + + DocumentFragment append()/prepend()/replaceChildren() added. + + + URL.origin should include the port (if it is not the default one). + + + Calling new DocumentFragment() now creates a properly initialized object. + + + XPathEvaluator.createExpression() and XPathExpression.evaluate() added. + + + Various exceptions fixed when XPathEvaluator.evaluate() is called without some optional parameters. + + + Documentation for changing the browser timezone/language added. + + + File.lastModifiedDate formatting fixed. + + + Document.lastModified now takes care of the browser timezone. + + + Intl.DateTimeFormat().resolvedOptions().locale support added. + + + core-js: Date/Time format functions are now taking care of the browser locale. + + + core-js: Date.prototype.toLocaleString takes care of locales argument. + + + core-js: Object.defineProperty() has to take care of ConsString. + + + Upgrade Apache commons-net to 3.11.1. + + + Fix NPE during click processing when JavaScript engine disabled. + + + + INCOMPATIBLE CHANGE: The signature of two methods from org.htmlunit.attachment.AttachmentHandler was changed. diff --git a/src/main/java/org/htmlunit/BrowserVersion.java b/src/main/java/org/htmlunit/BrowserVersion.java index 0e130688bd6..986473f86b4 100644 --- a/src/main/java/org/htmlunit/BrowserVersion.java +++ b/src/main/java/org/htmlunit/BrowserVersion.java @@ -22,6 +22,7 @@ import java.util.HashSet; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.TimeZone; @@ -84,7 +85,7 @@ public final class BrowserVersion implements Serializable { private static final String PLATFORM_WIN32 = "Win32"; /** Latest Firefox. */ - public static final BrowserVersion FIREFOX = new BrowserVersion(126, "FF"); + public static final BrowserVersion FIREFOX = new BrowserVersion(127, "FF"); private static final int FIREFOX_ESR_NUMERIC = 115; @@ -92,10 +93,10 @@ public final class BrowserVersion implements Serializable { public static final BrowserVersion FIREFOX_ESR = new BrowserVersion(FIREFOX_ESR_NUMERIC, "FF-ESR"); /** Latest Edge. */ - public static final BrowserVersion EDGE = new BrowserVersion(125, "Edge"); + public static final BrowserVersion EDGE = new BrowserVersion(126, "Edge"); /** Latest Chrome. */ - public static final BrowserVersion CHROME = new BrowserVersion(125, "Chrome"); + public static final BrowserVersion CHROME = new BrowserVersion(126, "Chrome"); /** * Array with all supported browsers. @@ -213,9 +214,9 @@ public final class BrowserVersion implements Serializable { CHROME.imgAcceptHeader_ = "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8"; CHROME.cssAcceptHeader_ = "text/css,*/*;q=0.1"; CHROME.scriptAcceptHeader_ = "*/*"; - CHROME.secClientHintUserAgentHeader_ = "\"Google Chrome\";v=\"" - + CHROME.getBrowserVersionNumeric() + "\", \"Chromium\";v=\"" - + CHROME.getBrowserVersionNumeric() + "\", \"Not.A/Brand\";v=\"24\""; + CHROME.secClientHintUserAgentHeader_ = "\"Not/A)Brand\";v=\"8\", \"Chromium\";v=\"" + + CHROME.getBrowserVersionNumeric() + "\", \"Google Chrome\";v=\"" + + CHROME.getBrowserVersionNumeric() + "\""; CHROME.fontHeights_ = new int[] { 0, 1, 2, 4, 5, 5, 6, 8, 9, 10, 11, 12, 15, 16, 16, 17, 18, 20, 21, 22, 23, 25, 26, 26, 27, 28, 30, 31, 32, 33, 34, 36, 37, 37, 38, 40, 42, 43, 44, 45, 47, 48, 48, 49, 51, 52, 53, 54, 55, 57, @@ -259,9 +260,9 @@ public final class BrowserVersion implements Serializable { EDGE.imgAcceptHeader_ = "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8"; EDGE.cssAcceptHeader_ = "text/css,*/*;q=0.1"; EDGE.scriptAcceptHeader_ = "*/*"; - EDGE.secClientHintUserAgentHeader_ = "\"Microsoft Edge\";v=\"" - + EDGE.getBrowserVersionNumeric() + "\", \"Chromium\";v=\"" - + EDGE.getBrowserVersionNumeric() + "\", \"Not.A/Brand\";v=\"24\""; + EDGE.secClientHintUserAgentHeader_ = "\"Not/A)Brand\";v=\"8\", \"Chromium\";v=\"" + + EDGE.getBrowserVersionNumeric() + "\", \"Microsoft Edge\";v=\"" + + EDGE.getBrowserVersionNumeric() + "\""; EDGE.fontHeights_ = new int[] { 0, 1, 2, 4, 5, 5, 6, 8, 9, 10, 11, 12, 15, 16, 16, 17, 18, 20, 21, 22, 23, 25, 26, 26, 27, 28, 30, 31, 32, 33, 34, 36, 37, 37, 38, 40, 42, 43, 44, 45, 47, 48, 48, 49, 51, 52, 53, 54, 55, 57, @@ -439,6 +440,10 @@ public final class BrowserVersion implements Serializable { initFeatures(); } + public boolean isSameBrowser(final BrowserVersion other) { + return Objects.equals(nickname_, other.nickname_) && browserVersionNumeric_ == other.browserVersionNumeric_; + } + private void initFeatures() { final SupportedBrowser expectedBrowser; if (isEdge()) { diff --git a/src/main/java/org/htmlunit/BrowserVersionFeatures.java b/src/main/java/org/htmlunit/BrowserVersionFeatures.java index e73d4339ef1..426a628438c 100644 --- a/src/main/java/org/htmlunit/BrowserVersionFeatures.java +++ b/src/main/java/org/htmlunit/BrowserVersionFeatures.java @@ -461,7 +461,7 @@ public enum BrowserVersionFeatures { /** * The default display style of multicol is 'block'. */ - @BrowserFeature({FF, FF_ESR}) + @BrowserFeature(FF_ESR) MULTICOL_BLOCK, /** The protocol setter does not check for special protocols. */ diff --git a/src/main/java/org/htmlunit/css/StyleAttributes.java b/src/main/java/org/htmlunit/css/StyleAttributes.java index 4da84b245f3..49209c9799d 100644 --- a/src/main/java/org/htmlunit/css/StyleAttributes.java +++ b/src/main/java/org/htmlunit/css/StyleAttributes.java @@ -2202,6 +2202,9 @@ public enum Definition { /** The style property {@code -moz-window-dragging}. */ MOZ_WINDOW_DRAGGING__("-moz-window-dragging", "-moz-window-dragging", ff("default")), + /** The style property {@code navigation}. */ + NAVIGATION("navigation", "navigation", chromeAndEdgeEmpty()), + /** The style property {@code negative}. */ NEGATIVE("negative", "negative", chromeAndEdgeEmpty()), @@ -3142,6 +3145,9 @@ public enum Definition { /** The style property {@code translate}. */ TRANSLATE("translate", "translate", chromeAndEdgeNone(), ffNone()), + /** The style property {@code types}. */ + TYPES("types", "types", chromeAndEdgeEmpty()), + /** The style property {@code unicodeBidi}. */ UNICODE_BIDI("unicodeBidi", "unicode-bidi", ff("isolate"), chromeAndEdge("isolate")), diff --git a/src/main/java/org/htmlunit/html/DomElement.java b/src/main/java/org/htmlunit/html/DomElement.java index ef50b4763af..f98badff843 100644 --- a/src/main/java/org/htmlunit/html/DomElement.java +++ b/src/main/java/org/htmlunit/html/DomElement.java @@ -1002,7 +1002,9 @@ public

P click(final boolean shiftKey, final boolean ctrlKey, f } final AbstractJavaScriptEngine jsEngine = webClient.getJavaScriptEngine(); - jsEngine.holdPosponedActions(); + if (webClient.isJavaScriptEnabled()) { + jsEngine.holdPosponedActions(); + } try { if (handleFocus) { // give focus to current element (if possible) or only remove it from previous one @@ -1051,7 +1053,9 @@ else if (this instanceof HtmlOption) { return click(event, shiftKey, ctrlKey, altKey, ignoreVisibility); } finally { - jsEngine.processPostponedActions(); + if (webClient.isJavaScriptEnabled()) { + jsEngine.processPostponedActions(); + } } } } @@ -1663,7 +1667,6 @@ public void setInnerHtml(final String source) throws SAXException, IOException { parseHtmlSnippet(source); } } - } /** diff --git a/src/main/java/org/htmlunit/html/DomNamespaceNode.java b/src/main/java/org/htmlunit/html/DomNamespaceNode.java index ae2f0c7974a..ea62a5f5ff6 100644 --- a/src/main/java/org/htmlunit/html/DomNamespaceNode.java +++ b/src/main/java/org/htmlunit/html/DomNamespaceNode.java @@ -68,10 +68,11 @@ protected DomNamespaceNode(final String namespaceURI, final String qualifiedName */ @Override public String getNamespaceURI() { - if (getPage().isHtmlPage() && !(getPage() instanceof XHtmlPage) + if (getPage().isHtmlPage() + && !(getPage() instanceof XHtmlPage) && Html.XHTML_NAMESPACE.equals(namespaceURI_) && XPathHelper.isProcessingXPath()) { - // for Xalan processing we have to strip the 'default' XHTML namespace for HTML pages to be able to find + // for xpath processing we have to strip the 'default' XHTML namespace for HTML pages to be able to find // the elements by XPath without needing to add the namespace to it return null; } @@ -84,7 +85,8 @@ public String getNamespaceURI() { @Override public String getLocalName() { final boolean caseSensitive = getPage().hasCaseSensitiveTagNames(); - if (!caseSensitive && XPathHelper.isProcessingXPath()) { // and this method was called from Xalan + if (!caseSensitive + && XPathHelper.isProcessingXPath()) { // and this method was called from xpath processor return localNameLC_; } return localName_; diff --git a/src/main/java/org/htmlunit/html/HtmlElement.java b/src/main/java/org/htmlunit/html/HtmlElement.java index f4ee0ba6f36..ec2b4056707 100644 --- a/src/main/java/org/htmlunit/html/HtmlElement.java +++ b/src/main/java/org/htmlunit/html/HtmlElement.java @@ -143,6 +143,8 @@ public String value() { protected static final String ATTRIBUTE_REQUIRED = "required"; /** Constant 'checked'. */ protected static final String ATTRIBUTE_CHECKED = "checked"; + /** Constant 'hidden'. */ + protected static final String ATTRIBUTE_HIDDEN = "hidden"; /** The listeners which are to be notified of attribute changes. */ private final List attributeListeners_ = new ArrayList<>(); @@ -1211,7 +1213,34 @@ private String getXPathToken() { * @return true if the hidden attribute is set. */ public boolean isHidden() { - return ATTRIBUTE_NOT_DEFINED != getAttributeDirect("hidden"); + return ATTRIBUTE_NOT_DEFINED != getAttributeDirect(ATTRIBUTE_HIDDEN); + } + + /** + * Sets the {@code hidden} property. + * @param hidden the {@code hidden} property + */ + public void setHidden(final String hidden) { + if ("false".equalsIgnoreCase(hidden)) { + removeAttribute(ATTRIBUTE_HIDDEN); + } + + if (StringUtils.isNotEmpty(hidden)) { + setAttribute(ATTRIBUTE_HIDDEN, ""); + } + } + + /** + * Sets the {@code hidden} property. + * @param hidden the {@code hidden} property + */ + public void setHidden(final boolean hidden) { + if (hidden) { + setAttribute("hidden", ""); + return; + } + + removeAttribute("hidden"); } /** diff --git a/src/main/java/org/htmlunit/html/HtmlTitle.java b/src/main/java/org/htmlunit/html/HtmlTitle.java index 543db8decab..c49e6fc0089 100644 --- a/src/main/java/org/htmlunit/html/HtmlTitle.java +++ b/src/main/java/org/htmlunit/html/HtmlTitle.java @@ -79,4 +79,31 @@ protected boolean isEmptyXmlTagExpanded() { public DisplayStyle getDefaultStyleDisplay() { return DisplayStyle.NONE; } + + /** + * Returns the {@code text} attribute. + * @return the {@code text} attribute + */ + public String getText() { + final DomNode firstChild = getFirstChild(); + if (firstChild != null) { + return firstChild.getNodeValue(); + } + return ""; + } + + /** + * Sets the {@code text} attribute. + * @param text the {@code text} attribute + */ + public void setText(final String text) { + DomNode firstChild = getFirstChild(); + if (firstChild == null) { + firstChild = new DomText(getPage(), text); + appendChild(firstChild); + } + else { + firstChild.setNodeValue(text); + } + } } diff --git a/src/main/java/org/htmlunit/html/ScriptElementSupport.java b/src/main/java/org/htmlunit/html/ScriptElementSupport.java index af8f89f30b8..583211e3365 100644 --- a/src/main/java/org/htmlunit/html/ScriptElementSupport.java +++ b/src/main/java/org/htmlunit/html/ScriptElementSupport.java @@ -82,8 +82,8 @@ public static void onAllChildrenAddedToPage(final DomElement element, final bool final ScriptElement script = (ScriptElement) element; final String srcAttrib = script.getSrcAttribute(); - final boolean hasSrcAttrib = ATTRIBUTE_NOT_DEFINED == srcAttrib; - if (!hasSrcAttrib && script.isDeferred()) { + final boolean hasNoSrcAttrib = ATTRIBUTE_NOT_DEFINED == srcAttrib; + if (!hasNoSrcAttrib && script.isDeferred()) { return; } @@ -91,9 +91,9 @@ public static void onAllChildrenAddedToPage(final DomElement element, final bool if (webWindow != null) { final StringBuilder description = new StringBuilder() .append("Execution of ") - .append(hasSrcAttrib ? "inline " : "external ") + .append(hasNoSrcAttrib ? "inline " : "external ") .append(element.getClass().getSimpleName()); - if (!hasSrcAttrib) { + if (!hasNoSrcAttrib) { description.append(" (").append(srcAttrib).append(')'); } final PostponedAction action = new PostponedAction(element.getPage(), description.toString()) { diff --git a/src/main/java/org/htmlunit/html/parser/neko/HtmlUnitNekoDOMBuilder.java b/src/main/java/org/htmlunit/html/parser/neko/HtmlUnitNekoDOMBuilder.java index 3619e7d59b2..4b63eb689ef 100644 --- a/src/main/java/org/htmlunit/html/parser/neko/HtmlUnitNekoDOMBuilder.java +++ b/src/main/java/org/htmlunit/html/parser/neko/HtmlUnitNekoDOMBuilder.java @@ -575,7 +575,9 @@ else if (currentNode_ instanceof HtmlImage) { @Override public void endDocument() throws SAXException { handleCharacters(); - page_.setEndLocation(locator_.getLineNumber(), locator_.getColumnNumber()); + if (locator_ != null) { + page_.setEndLocation(locator_.getLineNumber(), locator_.getColumnNumber()); + } } /** {@inheritDoc} */ diff --git a/src/main/java/org/htmlunit/html/parser/neko/HtmlUnitNekoHtmlParser.java b/src/main/java/org/htmlunit/html/parser/neko/HtmlUnitNekoHtmlParser.java index 7393a899727..595a6931afb 100644 --- a/src/main/java/org/htmlunit/html/parser/neko/HtmlUnitNekoHtmlParser.java +++ b/src/main/java/org/htmlunit/html/parser/neko/HtmlUnitNekoHtmlParser.java @@ -134,10 +134,13 @@ public void parseFragment(final DomNode parent, final DomNode context, final Str node = node.getParentNode(); } if (ancestors.isEmpty() || !"html".equals(ancestors.get(0).getLocalpart())) { - ancestors.add(0, new QName(null, "html", null, null)); + ancestors.add(new QName(null, "html", null, null)); + ancestors.add(new QName(null, "body", null, null)); } - if (ancestors.size() == 1 || !"body".equals(ancestors.get(1).getLocalpart())) { - ancestors.add(1, new QName(null, "body", null, null)); + else if (ancestors.size() == 1 + || (!"body".equals(ancestors.get(1).getLocalpart()) + && !"head".equals(ancestors.get(1).getLocalpart()))) { + ancestors.add(new QName(null, "body", null, null)); } domBuilder.setFeature(HTMLScanner.ALLOW_SELFCLOSING_TAGS, true); diff --git a/src/main/java/org/htmlunit/html/serializer/HtmlSerializerInnerOuterText.java b/src/main/java/org/htmlunit/html/serializer/HtmlSerializerInnerOuterText.java index f8e8ac178b5..2c4ab55c875 100644 --- a/src/main/java/org/htmlunit/html/serializer/HtmlSerializerInnerOuterText.java +++ b/src/main/java/org/htmlunit/html/serializer/HtmlSerializerInnerOuterText.java @@ -18,7 +18,7 @@ import org.apache.commons.lang3.StringUtils; import org.htmlunit.BrowserVersion; -import org.htmlunit.Page; +import org.htmlunit.SgmlPage; import org.htmlunit.WebWindow; import org.htmlunit.css.ComputedCssStyleDeclaration; import org.htmlunit.css.StyleAttributes.Definition; @@ -244,31 +244,34 @@ protected void appendDetails(final HtmlSerializerTextBuilder builder, private static Mode whiteSpaceStyle(final DomNode domNode, final Mode defaultMode) { if (domNode instanceof DomElement) { - final Page page = domNode.getPage(); + final SgmlPage page = domNode.getPage(); if (page != null) { - final WebWindow window = page.getEnclosingWindow(); - if (window.getWebClient().getOptions().isCssEnabled()) { + if (page.getWebClient().getOptions().isCssEnabled()) { DomNode node = domNode; while (node != null) { if (node instanceof DomElement) { - final ComputedCssStyleDeclaration style = - window.getComputedStyle((DomElement) domNode, null); - final String value = style.getStyleAttribute(Definition.WHITE_SPACE, false); - if (StringUtils.isNoneEmpty(value)) { - if ("normal".equalsIgnoreCase(value)) { - return Mode.WHITE_SPACE_NORMAL; - } - if ("nowrap".equalsIgnoreCase(value)) { - return Mode.WHITE_SPACE_NORMAL; - } - if ("pre".equalsIgnoreCase(value)) { - return Mode.WHITE_SPACE_PRE; - } - if ("pre-wrap".equalsIgnoreCase(value)) { - return Mode.WHITE_SPACE_PRE; - } - if ("pre-line".equalsIgnoreCase(value)) { - return Mode.WHITE_SPACE_PRE_LINE; + final WebWindow window = page.getEnclosingWindow(); + if (window != null) { + final ComputedCssStyleDeclaration style = + window.getComputedStyle((DomElement) domNode, null); + final String value = style.getStyleAttribute(Definition.WHITE_SPACE, false); + + if (StringUtils.isNoneEmpty(value)) { + if ("normal".equalsIgnoreCase(value)) { + return Mode.WHITE_SPACE_NORMAL; + } + if ("nowrap".equalsIgnoreCase(value)) { + return Mode.WHITE_SPACE_NORMAL; + } + if ("pre".equalsIgnoreCase(value)) { + return Mode.WHITE_SPACE_PRE; + } + if ("pre-wrap".equalsIgnoreCase(value)) { + return Mode.WHITE_SPACE_PRE; + } + if ("pre-line".equalsIgnoreCase(value)) { + return Mode.WHITE_SPACE_PRE_LINE; + } } } } @@ -347,6 +350,9 @@ public void appendRequiredLineBreak() { // see https://drafts.csswg.org/css-text-3/#white-space public void append(final String content, final Mode mode) { + if (content == null) { + return; + } int length = content.length(); if (length == 0) { return; diff --git a/src/main/java/org/htmlunit/html/serializer/HtmlSerializerNormalizedText.java b/src/main/java/org/htmlunit/html/serializer/HtmlSerializerNormalizedText.java index 634d82a5de3..3a84d2ad2b1 100644 --- a/src/main/java/org/htmlunit/html/serializer/HtmlSerializerNormalizedText.java +++ b/src/main/java/org/htmlunit/html/serializer/HtmlSerializerNormalizedText.java @@ -611,6 +611,9 @@ public HtmlSerializerTextBuilder() { } public void append(final String content, final Mode mode) { + if (content == null) { + return; + } final int length = content.length(); if (length == 0) { return; diff --git a/src/main/java/org/htmlunit/html/serializer/HtmlSerializerVisibleText.java b/src/main/java/org/htmlunit/html/serializer/HtmlSerializerVisibleText.java index 776d9a283e8..3994d67cf16 100644 --- a/src/main/java/org/htmlunit/html/serializer/HtmlSerializerVisibleText.java +++ b/src/main/java/org/htmlunit/html/serializer/HtmlSerializerVisibleText.java @@ -793,6 +793,9 @@ public HtmlSerializerTextBuilder() { // see https://drafts.csswg.org/css-text-3/#white-space public void append(final String content, final Mode mode) { + if (content == null) { + return; + } int length = content.length(); if (length == 0) { return; diff --git a/src/main/java/org/htmlunit/html/xpath/HtmlUnitPrefixResolver.java b/src/main/java/org/htmlunit/html/xpath/HtmlUnitPrefixResolver.java index 282e6b7a9c6..46fe6e3feda 100644 --- a/src/main/java/org/htmlunit/html/xpath/HtmlUnitPrefixResolver.java +++ b/src/main/java/org/htmlunit/html/xpath/HtmlUnitPrefixResolver.java @@ -29,13 +29,13 @@ * @author Ahmed Ashour * @author Ronald Brill */ -final class HtmlUnitPrefixResolver extends PrefixResolverDefault { +public final class HtmlUnitPrefixResolver extends PrefixResolverDefault { /** * Creates a new instance. * @param xpathExpressionContext the context from which XPath expression prefixes will be resolved */ - HtmlUnitPrefixResolver(final Node xpathExpressionContext) { + public HtmlUnitPrefixResolver(final Node xpathExpressionContext) { super(xpathExpressionContext); } diff --git a/src/main/java/org/htmlunit/html/xpath/XPathAdapter.java b/src/main/java/org/htmlunit/html/xpath/XPathAdapter.java index 7c7b3831fc9..40878ebd579 100644 --- a/src/main/java/org/htmlunit/html/xpath/XPathAdapter.java +++ b/src/main/java/org/htmlunit/html/xpath/XPathAdapter.java @@ -35,7 +35,7 @@ * @author Ahmed Ashour * @author Ronald Brill */ -class XPathAdapter { +public class XPathAdapter { private enum STATE { DEFAULT, @@ -58,22 +58,17 @@ private void initFunctionTable() { * Constructor. * @param exprString the XPath expression * @param prefixResolver a prefix resolver to use to resolve prefixes to namespace URIs - * @param errorListener the error listener, or {@code null} if default should be used * @param caseSensitive whether the attributes should be case-sensitive * @throws TransformerException if a syntax or other error occurs */ - XPathAdapter(final String exprString, final PrefixResolver prefixResolver, - final ErrorListener errorListener, final boolean caseSensitive) + public XPathAdapter(final String exprString, final PrefixResolver prefixResolver, final boolean caseSensitive) throws TransformerException { initFunctionTable(); - ErrorListener errListener = errorListener; - if (errListener == null) { - errListener = new DefaultErrorHandler(); - } - final XPathParser parser = new XPathParser(errListener); - final Compiler compiler = new Compiler(errorListener, funcTable_); + final ErrorListener errorHandler = new DefaultErrorHandler(); + final XPathParser parser = new XPathParser(errorHandler); + final Compiler compiler = new Compiler(errorHandler, funcTable_); final String expression = preProcessXPath(exprString, caseSensitive); parser.initXPath(compiler, expression, prefixResolver); diff --git a/src/main/java/org/htmlunit/html/xpath/XPathHelper.java b/src/main/java/org/htmlunit/html/xpath/XPathHelper.java index af75f928adf..7d5ce4a750c 100644 --- a/src/main/java/org/htmlunit/html/xpath/XPathHelper.java +++ b/src/main/java/org/htmlunit/html/xpath/XPathHelper.java @@ -58,22 +58,50 @@ private XPathHelper() { * Evaluates an XPath expression from the specified node, returning the resultant nodes. * * @param the type class - * @param node the node to start searching from + * @param contextNode the node to start searching from * @param xpathExpr the XPath expression - * @param resolver the prefix resolver to use for resolving namespace prefixes, or null + * @param prefixResolver the prefix resolver to use for resolving namespace prefixes, or null * @return the list of objects found */ @SuppressWarnings("unchecked") - public static List getByXPath(final DomNode node, final String xpathExpr, - final PrefixResolver resolver) { + public static List getByXPath(final DomNode contextNode, final String xpathExpr, + final PrefixResolver prefixResolver) { if (xpathExpr == null) { throw new IllegalArgumentException("Null is not a valid XPath expression"); } - PROCESS_XPATH_.set(Boolean.TRUE); + PrefixResolver resolver = prefixResolver; + if (resolver == null) { + final Node xpathExpressionContext; + if (contextNode.getNodeType() == Node.DOCUMENT_NODE) { + xpathExpressionContext = ((Document) contextNode).getDocumentElement(); + } + else { + xpathExpressionContext = contextNode; + } + + resolver = new HtmlUnitPrefixResolver(xpathExpressionContext); + } + + try { + final boolean caseSensitive = contextNode.getPage().hasCaseSensitiveTagNames(); + final XPathAdapter xpath = new XPathAdapter(xpathExpr, resolver, caseSensitive); + return getByXPath(contextNode, xpath, prefixResolver); + } + catch (final Exception e) { + throw new RuntimeException("Could not retrieve XPath >" + xpathExpr + "< on " + contextNode, e); + } + } + + public static List getByXPath(final Node node, final XPathAdapter xpath, + final PrefixResolver prefixResolver) throws TransformerException { final List list = new ArrayList<>(); + + PROCESS_XPATH_.set(Boolean.TRUE); try { - final XObject result = evaluateXPath(node, xpathExpr, resolver); + final XPathContext xpathSupport = new XPathContext(); + final int ctxtNode = xpathSupport.getDTMHandleFromNode(node); + final XObject result = xpath.execute(xpathSupport, ctxtNode, prefixResolver); if (result instanceof XNodeSet) { final NodeList nodelist = result.nodelist(); @@ -94,12 +122,10 @@ else if (result instanceof XString) { throw new RuntimeException("Unproccessed " + result.getClass().getName()); } } - catch (final Exception e) { - throw new RuntimeException("Could not retrieve XPath >" + xpathExpr + "< on " + node, e); - } finally { PROCESS_XPATH_.set(Boolean.FALSE); } + return list; } @@ -111,35 +137,4 @@ public static boolean isProcessingXPath() { return PROCESS_XPATH_.get().booleanValue(); } - /** - * Evaluates an XPath expression to an XObject. - * @param contextNode the node to start searching from - * @param str a valid XPath string - * @param prefixResolver prefix resolver to use for resolving namespace prefixes, or null - * @return an XObject, which can be used to obtain a string, number, nodelist, etc (should never be {@code null}) - * @throws TransformerException if a syntax or other error occurs - */ - private static XObject evaluateXPath(final DomNode contextNode, - final String str, final PrefixResolver prefixResolver) throws TransformerException { - final XPathContext xpathSupport = new XPathContext(); - final Node xpathExpressionContext; - if (contextNode.getNodeType() == Node.DOCUMENT_NODE) { - xpathExpressionContext = ((Document) contextNode).getDocumentElement(); - } - else { - xpathExpressionContext = contextNode; - } - - PrefixResolver resolver = prefixResolver; - if (resolver == null) { - resolver = new HtmlUnitPrefixResolver(xpathExpressionContext); - } - - final boolean caseSensitive = contextNode.getPage().hasCaseSensitiveTagNames(); - - final XPathAdapter xpath = new XPathAdapter(str, resolver, null, caseSensitive); - final int ctxtNode = xpathSupport.getDTMHandleFromNode(contextNode); - return xpath.execute(xpathSupport, ctxtNode, prefixResolver); - } - } diff --git a/src/main/java/org/htmlunit/javascript/HtmlUnitContextFactory.java b/src/main/java/org/htmlunit/javascript/HtmlUnitContextFactory.java index baa0f9416a4..83c6dddec4e 100644 --- a/src/main/java/org/htmlunit/javascript/HtmlUnitContextFactory.java +++ b/src/main/java/org/htmlunit/javascript/HtmlUnitContextFactory.java @@ -244,6 +244,7 @@ protected Context makeContext() { final TimeoutContext cx = new TimeoutContext(this); cx.setLanguageVersion(Context.VERSION_ES6); cx.setLocale(browserVersion_.getBrowserLocale()); + cx.setTimeZone(browserVersion_.getSystemTimezone()); // make sure no java classes are usable from js cx.setClassShutter(fullClassName -> { diff --git a/src/main/java/org/htmlunit/javascript/JavaScriptEngine.java b/src/main/java/org/htmlunit/javascript/JavaScriptEngine.java index e73896d1d7e..0c670ba113c 100644 --- a/src/main/java/org/htmlunit/javascript/JavaScriptEngine.java +++ b/src/main/java/org/htmlunit/javascript/JavaScriptEngine.java @@ -73,7 +73,6 @@ import org.htmlunit.javascript.configuration.JavaScriptConfiguration; import org.htmlunit.javascript.configuration.ProxyAutoConfigJavaScriptConfiguration; import org.htmlunit.javascript.host.ConsoleCustom; -import org.htmlunit.javascript.host.DateCustom; import org.htmlunit.javascript.host.NumberCustom; import org.htmlunit.javascript.host.URLSearchParams; import org.htmlunit.javascript.host.Window; @@ -435,9 +434,6 @@ public static void configureRhino(final WebClient webClient, NativeFunctionToStringFunction.installFix(scriptable, browserVersion); - datePrototype.defineFunctionProperties(new String[] {"toLocaleDateString", "toLocaleTimeString"}, - DateCustom.class, ScriptableObject.DONTENUM); - numberPrototype.defineFunctionProperties(new String[] {"toLocaleString"}, NumberCustom.class, ScriptableObject.DONTENUM); diff --git a/src/main/java/org/htmlunit/javascript/configuration/JavaScriptConfiguration.java b/src/main/java/org/htmlunit/javascript/configuration/JavaScriptConfiguration.java index 610d4711408..398bf5c2ae4 100644 --- a/src/main/java/org/htmlunit/javascript/configuration/JavaScriptConfiguration.java +++ b/src/main/java/org/htmlunit/javascript/configuration/JavaScriptConfiguration.java @@ -67,7 +67,6 @@ import org.htmlunit.javascript.host.URLSearchParams; import org.htmlunit.javascript.host.WebSocket; import org.htmlunit.javascript.host.Window; -import org.htmlunit.javascript.host.XPathExpression; import org.htmlunit.javascript.host.animations.Animation; import org.htmlunit.javascript.host.animations.AnimationEvent; import org.htmlunit.javascript.host.animations.KeyframeEffect; @@ -164,6 +163,7 @@ import org.htmlunit.javascript.host.dom.Text; import org.htmlunit.javascript.host.dom.TreeWalker; import org.htmlunit.javascript.host.dom.XPathEvaluator; +import org.htmlunit.javascript.host.dom.XPathExpression; import org.htmlunit.javascript.host.dom.XPathNSResolver; import org.htmlunit.javascript.host.dom.XPathResult; import org.htmlunit.javascript.host.event.AudioProcessingEvent; @@ -715,7 +715,7 @@ public final class JavaScriptConfiguration extends AbstractJavaScriptConfigurati WebkitSpeechRecognitionEvent.class, WebSocket.class, WheelEvent.class, Window.class, Worker.class, XMLDocument.class, XMLHttpRequest.class, XMLHttpRequestEventTarget.class, XMLHttpRequestUpload.class, XMLSerializer.class, - XPathEvaluator.class, XPathExpression.class, + XPathEvaluator.class, XPathEvaluator.class, XPathExpression.class, XPathNSResolver.class, XPathResult.class, XSLTProcessor.class }; diff --git a/src/main/java/org/htmlunit/javascript/host/DateCustom.java b/src/main/java/org/htmlunit/javascript/host/DateCustom.java deleted file mode 100644 index a49b5b13054..00000000000 --- a/src/main/java/org/htmlunit/javascript/host/DateCustom.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2002-2024 Gargoyle Software Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.htmlunit.javascript.host; - -import java.util.Date; - -import org.apache.commons.lang3.time.FastDateFormat; -import org.htmlunit.BrowserVersion; -import org.htmlunit.corejs.javascript.Context; -import org.htmlunit.corejs.javascript.Function; -import org.htmlunit.corejs.javascript.Scriptable; - -/** - * Contains some missing features of Rhino NativeDate. - * - * @author Ahmed Ashour - * @author Ronald Brill - * @author Frank Danek - */ -public final class DateCustom { - - private DateCustom() { - } - - /** - * Converts a date to a string, returning the "date" portion using the operating system's locale's conventions. - * @param context the JavaScript context - * @param scope the scope - * @param thisObj the scriptable - * @param args the arguments passed into the method - * @param function the function - * @return converted string - */ - public static String toLocaleDateString(final Context context, final Scriptable scope, - final Scriptable thisObj, final Object[] args, final Function function) { - final BrowserVersion browserVersion = ((Window) thisObj.getParentScope()).getBrowserVersion(); - final String formatString = "M/d/yyyy"; - final FastDateFormat format = FastDateFormat.getInstance(formatString, browserVersion.getBrowserLocale()); - return format.format(getDateValue(thisObj)); - } - - /** - * Converts a date to a string, returning the "time" portion using the current locale's conventions. - * @param context the JavaScript context - * @param scope the scope - * @param thisObj the scriptable - * @param args the arguments passed into the method - * @param function the function - * @return converted string - */ - public static String toLocaleTimeString(final Context context, final Scriptable scope, - final Scriptable thisObj, final Object[] args, final Function function) { - final String formatString; - final BrowserVersion browserVersion = ((Window) thisObj.getParentScope()).getBrowserVersion(); - formatString = "h:mm:ss a"; - final FastDateFormat format = FastDateFormat.getInstance(formatString, browserVersion.getBrowserLocale()); - return format.format(getDateValue(thisObj)); - } - - private static long getDateValue(final Scriptable thisObj) { - final Date date = (Date) Context.jsToJava(thisObj, Date.class); - return date.getTime(); - } -} diff --git a/src/main/java/org/htmlunit/javascript/host/URL.java b/src/main/java/org/htmlunit/javascript/host/URL.java index ebe08c170c6..70503cf857b 100644 --- a/src/main/java/org/htmlunit/javascript/host/URL.java +++ b/src/main/java/org/htmlunit/javascript/host/URL.java @@ -260,7 +260,11 @@ public Object getOrigin() { return null; } - return url_.getProtocol() + "://" + url_.getHost(); + if (url_.getPort() < 0 || url_.getPort() == url_.getDefaultPort()) { + return url_.getProtocol() + "://" + url_.getHost(); + } + + return url_.getProtocol() + "://" + url_.getHost() + ':' + url_.getPort(); } /** diff --git a/src/main/java/org/htmlunit/javascript/host/XPathExpression.java b/src/main/java/org/htmlunit/javascript/host/XPathExpression.java deleted file mode 100644 index 4cb7c84c4bd..00000000000 --- a/src/main/java/org/htmlunit/javascript/host/XPathExpression.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2002-2024 Gargoyle Software Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.htmlunit.javascript.host; - -import org.htmlunit.javascript.HtmlUnitScriptable; -import org.htmlunit.javascript.configuration.JsxClass; -import org.htmlunit.javascript.configuration.JsxConstructor; - -/** - * A JavaScript object for {@code XPathExpression}. - * - * @author Ahmed Ashour - * @author Ronald Brill - */ -@JsxClass -public class XPathExpression extends HtmlUnitScriptable { - - /** - * Creates a new instance. - */ - public XPathExpression() { - } - - /** - * JavaScript constructor. - */ - @JsxConstructor - public void jsConstructor() { - } -} diff --git a/src/main/java/org/htmlunit/javascript/host/dom/Document.java b/src/main/java/org/htmlunit/javascript/host/dom/Document.java index 420ef63e38d..01d89310e86 100644 --- a/src/main/java/org/htmlunit/javascript/host/dom/Document.java +++ b/src/main/java/org/htmlunit/javascript/host/dom/Document.java @@ -29,7 +29,8 @@ import java.io.IOException; import java.io.Serializable; import java.net.URL; -import java.text.SimpleDateFormat; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.Collections; import java.util.Date; import java.util.HashMap; @@ -160,8 +161,9 @@ public class Document extends Node { /** https://developer.mozilla.org/en/Rich-Text_Editing_in_Mozilla#Executing_Commands */ private static final Set EXECUTE_CMDS_FF = new HashSet<>(); private static final Set EXECUTE_CMDS_CHROME = new HashSet<>(); - /** The format to use for the lastModified attribute. */ - private static final String LAST_MODIFIED_DATE_FORMAT = "MM/dd/yyyy HH:mm:ss"; + /** The formatter to use for the lastModified attribute. */ + private static final DateTimeFormatter LAST_MODIFIED_DATE_FORMATTER + = DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm:ss"); /** Contains all supported DOM level 2 events. */ private static final Map> SUPPORTED_DOM2_EVENT_TYPE_MAP; @@ -1857,7 +1859,9 @@ public String getLastModified() { else { lastModified = new Date(); } - lastModified_ = new SimpleDateFormat(LAST_MODIFIED_DATE_FORMAT, Locale.ROOT).format(lastModified); + + final ZoneId zoneid = Context.getCurrentContext().getTimeZone().toZoneId(); + lastModified_ = LAST_MODIFIED_DATE_FORMATTER.format(lastModified.toInstant().atZone(zoneid)); } return lastModified_; } diff --git a/src/main/java/org/htmlunit/javascript/host/dom/DocumentFragment.java b/src/main/java/org/htmlunit/javascript/host/dom/DocumentFragment.java index c860a8ef3da..e354b9a53d7 100644 --- a/src/main/java/org/htmlunit/javascript/host/dom/DocumentFragment.java +++ b/src/main/java/org/htmlunit/javascript/host/dom/DocumentFragment.java @@ -14,9 +14,13 @@ */ package org.htmlunit.javascript.host.dom; +import org.htmlunit.corejs.javascript.Context; +import org.htmlunit.corejs.javascript.Function; +import org.htmlunit.corejs.javascript.Scriptable; import org.htmlunit.cssparser.parser.CSSException; import org.htmlunit.html.DomDocumentFragment; import org.htmlunit.html.DomNode; +import org.htmlunit.html.HtmlPage; import org.htmlunit.javascript.HtmlUnitScriptable; import org.htmlunit.javascript.JavaScriptEngine; import org.htmlunit.javascript.configuration.JsxClass; @@ -52,6 +56,55 @@ public DocumentFragment() { @JsxConstructor public void jsConstructor() { super.jsConstructor(); + + final HtmlPage page = (HtmlPage) getWindow().getWebWindow().getEnclosedPage(); + final DomDocumentFragment fragment = new DomDocumentFragment(page); + setDomNode(fragment); + } + + /** + * Inserts a set of Node objects or string objects after the last child + * of the document fragment. String objects are inserted as equivalent Text nodes. + * @param context the context + * @param scope the scope + * @param thisObj this object + * @param args the arguments + * @param function the function + */ + @JsxFunction + public static void append(final Context context, final Scriptable scope, + final Scriptable thisObj, final Object[] args, final Function function) { + Node.append(context, thisObj, args, function); + } + + /** + * Inserts a set of Node objects or string objects before the first child + * of the document fragment. String objects are inserted as equivalent Text nodes. + * @param context the context + * @param scope the scope + * @param thisObj this object + * @param args the arguments + * @param function the function + */ + @JsxFunction + public static void prepend(final Context context, final Scriptable scope, + final Scriptable thisObj, final Object[] args, final Function function) { + Node.prepend(context, thisObj, args, function); + } + + /** + * Replaces the existing children of a DocumentFragment with a specified + * new set of children. These can be string or Node objects. + * @param context the context + * @param scope the scope + * @param thisObj this object + * @param args the arguments + * @param function the function + */ + @JsxFunction + public static void replaceChildren(final Context context, final Scriptable scope, + final Scriptable thisObj, final Object[] args, final Function function) { + Node.replaceChildren(context, thisObj, args, function); } /** diff --git a/src/main/java/org/htmlunit/javascript/host/dom/Node.java b/src/main/java/org/htmlunit/javascript/host/dom/Node.java index 48773329af7..9c8364405b1 100644 --- a/src/main/java/org/htmlunit/javascript/host/dom/Node.java +++ b/src/main/java/org/htmlunit/javascript/host/dom/Node.java @@ -967,16 +967,16 @@ protected static void after(final Context context, final Scriptable thisObj, fin */ protected static void append(final Context context, final Scriptable thisObj, final Object[] args, final Function function) { - if (!(thisObj instanceof Element)) { + if (!(thisObj instanceof Node)) { throw JavaScriptEngine.typeError("Illegal invocation"); } - final DomNode thisDomNode = ((Node) thisObj).getDomNodeOrDie(); + final Node thisNode = (Node) thisObj; + final DomNode thisDomNode = thisNode.getDomNodeOrDie(); for (final Object arg : args) { - final Node node = toNodeOrTextNode((Node) thisObj, arg); - final DomNode newNode = node.getDomNodeOrDie(); - thisDomNode.appendChild(newNode); + final Node node = toNodeOrTextNode(thisNode, arg); + thisDomNode.appendChild(node.getDomNodeOrDie()); } } @@ -990,14 +990,16 @@ protected static void append(final Context context, final Scriptable thisObj, fi */ protected static void prepend(final Context context, final Scriptable thisObj, final Object[] args, final Function function) { - if (!(thisObj instanceof Element)) { + if (!(thisObj instanceof Node)) { throw JavaScriptEngine.typeError("Illegal invocation"); } - final DomNode thisDomNode = ((Node) thisObj).getDomNodeOrDie(); + final Node thisNode = (Node) thisObj; + final DomNode thisDomNode = thisNode.getDomNodeOrDie(); final DomNode firstChild = thisDomNode.getFirstChild(); + for (final Object arg : args) { - final Node node = toNodeOrTextNode((Node) thisObj, arg); + final Node node = toNodeOrTextNode(thisNode, arg); final DomNode newNode = node.getDomNodeOrDie(); if (firstChild == null) { thisDomNode.appendChild(newNode); @@ -1018,15 +1020,16 @@ protected static void prepend(final Context context, final Scriptable thisObj, f */ protected static void replaceChildren(final Context context, final Scriptable thisObj, final Object[] args, final Function function) { - if (!(thisObj instanceof Element)) { + if (!(thisObj instanceof Node)) { throw JavaScriptEngine.typeError("Illegal invocation"); } - final DomNode thisDomNode = ((Node) thisObj).getDomNodeOrDie(); + final Node thisNode = (Node) thisObj; + final DomNode thisDomNode = thisNode.getDomNodeOrDie(); thisDomNode.removeAllChildren(); for (final Object arg : args) { - final Node node = toNodeOrTextNode((Node) thisObj, arg); + final Node node = toNodeOrTextNode(thisNode, arg); thisDomNode.appendChild(node.getDomNodeOrDie()); } } diff --git a/src/main/java/org/htmlunit/javascript/host/dom/XPathEvaluator.java b/src/main/java/org/htmlunit/javascript/host/dom/XPathEvaluator.java index ef8feef1d52..1b33d05d50d 100644 --- a/src/main/java/org/htmlunit/javascript/host/dom/XPathEvaluator.java +++ b/src/main/java/org/htmlunit/javascript/host/dom/XPathEvaluator.java @@ -14,13 +14,18 @@ */ package org.htmlunit.javascript.host.dom; +import org.htmlunit.corejs.javascript.Context; +import org.htmlunit.corejs.javascript.Function; import org.htmlunit.corejs.javascript.NativeFunction; +import org.htmlunit.corejs.javascript.Scriptable; +import org.htmlunit.html.DomNode; import org.htmlunit.javascript.HtmlUnitScriptable; import org.htmlunit.javascript.JavaScriptEngine; import org.htmlunit.javascript.configuration.JsxClass; import org.htmlunit.javascript.configuration.JsxConstructor; import org.htmlunit.javascript.configuration.JsxFunction; import org.htmlunit.javascript.host.NativeFunctionPrefixResolver; +import org.htmlunit.javascript.host.Window; import org.htmlunit.xpath.xml.utils.PrefixResolver; /** @@ -76,12 +81,6 @@ public XPathNSResolver createNSResolver(final Node nodeResolver) { public XPathResult evaluate(final String expression, final Object contextNodeObj, final Object resolver, final int type, final Object result) { try { - XPathResult xPathResult = (XPathResult) result; - if (xPathResult == null) { - xPathResult = new XPathResult(); - xPathResult.setParentScope(getParentScope()); - xPathResult.setPrototype(getPrototype(xPathResult.getClass())); - } // contextNodeObj can be either a node or an array with the node as the first element. if (!(contextNodeObj instanceof Node)) { throw JavaScriptEngine.reportRuntimeError("Illegal value for parameter 'context'"); @@ -96,6 +95,17 @@ else if (resolver instanceof NativeFunction) { prefixResolver = new NativeFunctionPrefixResolver( (NativeFunction) resolver, contextNode.getParentScope()); } + + final XPathResult xPathResult; + if (result instanceof XPathResult) { + xPathResult = (XPathResult) result; + } + else { + xPathResult = new XPathResult(); + xPathResult.setParentScope(getParentScope()); + xPathResult.setPrototype(getPrototype(xPathResult.getClass())); + } + xPathResult.init(contextNode.getDomNodeOrDie().getByXPath(expression, prefixResolver), type); return xPathResult; } @@ -104,4 +114,48 @@ else if (resolver instanceof NativeFunction) { } } + /** + * Compiles an XPathExpression which can then be used for (repeated) evaluations of the XPath expression. + * @param context the context + * @param scope the scope + * @param thisObj this object + * @param args the arguments + * @param function the function + * @return a XPathExpression representing the compiled form of the XPath expression. + */ + @JsxFunction + public static XPathExpression createExpression(final Context context, final Scriptable scope, + final Scriptable thisObj, final Object[] args, final Function function) { + if (args.length < 1) { + throw JavaScriptEngine.reportRuntimeError("Missing 'expression' parameter"); + } + + PrefixResolver prefixResolver = null; + if (args.length > 1) { + final Object resolver = args[1]; + if (resolver instanceof PrefixResolver) { + prefixResolver = (PrefixResolver) resolver; + } + else if (resolver instanceof NativeFunction) { + prefixResolver = new NativeFunctionPrefixResolver( + (NativeFunction) resolver, scope.getParentScope()); + } + } + + final XPathEvaluator evaluator = (XPathEvaluator) thisObj; + + try { + final String xpath = JavaScriptEngine.toString(args[0]); + final DomNode doc = ((Window) scope).getDocument().getDocumentElement().getDomNodeOrDie(); + final XPathExpression xPathExpression = new XPathExpression(xpath, prefixResolver, doc); + xPathExpression.setParentScope(evaluator.getParentScope()); + xPathExpression.setPrototype(evaluator.getPrototype(xPathExpression.getClass())); + + return xPathExpression; + } + catch (final Exception e) { + throw JavaScriptEngine.constructError("SyntaxError", + "Failed to compile xpath '" + args[0] + "' (" + e.getMessage() + ")"); + } + } } diff --git a/src/main/java/org/htmlunit/javascript/host/dom/XPathExpression.java b/src/main/java/org/htmlunit/javascript/host/dom/XPathExpression.java new file mode 100644 index 00000000000..4eda0f6577c --- /dev/null +++ b/src/main/java/org/htmlunit/javascript/host/dom/XPathExpression.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2002-2024 Gargoyle Software Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.htmlunit.javascript.host.dom; + +import javax.xml.transform.TransformerException; + +import org.htmlunit.corejs.javascript.Context; +import org.htmlunit.corejs.javascript.Function; +import org.htmlunit.corejs.javascript.Scriptable; +import org.htmlunit.html.DomNode; +import org.htmlunit.html.xpath.HtmlUnitPrefixResolver; +import org.htmlunit.html.xpath.XPathAdapter; +import org.htmlunit.html.xpath.XPathHelper; +import org.htmlunit.javascript.HtmlUnitScriptable; +import org.htmlunit.javascript.JavaScriptEngine; +import org.htmlunit.javascript.configuration.JsxClass; +import org.htmlunit.javascript.configuration.JsxConstructor; +import org.htmlunit.javascript.configuration.JsxFunction; +import org.htmlunit.xpath.xml.utils.PrefixResolver; +import org.w3c.dom.Node; + +/** + * A JavaScript object for {@code XPathExpression}. + * + * @author Ahmed Ashour + * @author Ronald Brill + */ +@JsxClass +public class XPathExpression extends HtmlUnitScriptable { + + private final XPathAdapter xpath_; + private final PrefixResolver prefixResolver_; + + /** + * Default constructor. + */ + public XPathExpression() { + xpath_ = null; + prefixResolver_ = null; + } + + /** + * JavaScript constructor. + */ + @JsxConstructor + public void jsConstructor() { + } + + XPathExpression(final String expression, final PrefixResolver prefixResolver, + final DomNode node) throws TransformerException { + PrefixResolver resolver = prefixResolver; + if (resolver == null) { + resolver = new HtmlUnitPrefixResolver(node); + } + prefixResolver_ = resolver; + final boolean caseSensitive = node.getPage().hasCaseSensitiveTagNames(); + xpath_ = new XPathAdapter(expression, prefixResolver, caseSensitive); + } + + /** + * Executes an XPath expression on the given node or document and returns an XPathResult. + * @param context the context + * @param scope the scope + * @param thisObj this object + * @param args the arguments + * @param function the function + * @return the result of the evaluation of the XPath expression + */ + @JsxFunction + public static XPathResult evaluate(final Context context, final Scriptable scope, + final Scriptable thisObj, final Object[] args, final Function function) { + if (args.length < 1) { + throw JavaScriptEngine.reportRuntimeError("Missing 'contextNode' parameter"); + } + + int type = 0; // ANY + if (args.length > 1) { + type = (int) JavaScriptEngine.toInteger(args[1]); + } + + Object result = null; + if (args.length > 2) { + result = args[2]; + } + + try { + final XPathExpression expression = (XPathExpression) thisObj; + + final Object contextNodeObj = args[0]; + if (!(contextNodeObj instanceof org.htmlunit.javascript.host.dom.Node)) { + throw JavaScriptEngine.reportRuntimeError("Illegal value for parameter 'context'"); + } + + final Node contextNode = ((org.htmlunit.javascript.host.dom.Node) contextNodeObj).getDomNodeOrDie(); + + final XPathResult xPathResult; + if (result instanceof XPathResult) { + xPathResult = (XPathResult) result; + } + else { + xPathResult = new XPathResult(); + xPathResult.setParentScope(expression.getParentScope()); + xPathResult.setPrototype(expression.getPrototype(xPathResult.getClass())); + } + + xPathResult.init(XPathHelper.getByXPath(contextNode, expression.xpath_, expression.prefixResolver_), type); + return xPathResult; + } + catch (final Exception e) { + throw JavaScriptEngine.reportRuntimeError("Failed to execute 'evaluate': " + e.getMessage()); + } + } +} diff --git a/src/main/java/org/htmlunit/javascript/host/file/File.java b/src/main/java/org/htmlunit/javascript/host/file/File.java index 6dcb9b9c4db..2abbefbe329 100644 --- a/src/main/java/org/htmlunit/javascript/host/file/File.java +++ b/src/main/java/org/htmlunit/javascript/host/file/File.java @@ -19,13 +19,13 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; -import java.util.Date; -import java.util.Locale; -import java.util.TimeZone; +import java.time.Instant; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import org.apache.commons.io.FileUtils; -import org.apache.commons.lang3.time.FastDateFormat; import org.htmlunit.BrowserVersion; +import org.htmlunit.corejs.javascript.Context; import org.htmlunit.corejs.javascript.NativeArray; import org.htmlunit.corejs.javascript.ScriptableObject; import org.htmlunit.javascript.JavaScriptEngine; @@ -42,7 +42,8 @@ */ @JsxClass public class File extends Blob { - private static final String LAST_MODIFIED_DATE_FORMAT = "EEE MMM dd yyyy HH:mm:ss 'GMT'Z (zzzz)"; + private static final DateTimeFormatter LAST_MODIFIED_DATE_FORMATTER + = DateTimeFormatter.ofPattern("EEE MMM dd yyyy HH:mm:ss 'GMT'Z"); private static class FileBackend extends Backend { private final java.io.File file_; @@ -139,13 +140,14 @@ public String getName() { */ @JsxGetter({CHROME, EDGE}) public String getLastModifiedDate() { - final Date date = new Date(getLastModified()); - final BrowserVersion browser = getBrowserVersion(); - final Locale locale = browser.getBrowserLocale(); - final TimeZone timezone = browser.getSystemTimezone(); - - final FastDateFormat format = FastDateFormat.getInstance(LAST_MODIFIED_DATE_FORMAT, timezone, locale); - return format.format(date); + final Context cx = Context.getCurrentContext(); + final ZoneId zoneid = cx.getTimeZone().toZoneId(); + + // strange only the time zone is locale dependent + String date = LAST_MODIFIED_DATE_FORMATTER.format(Instant.ofEpochMilli(getLastModified()).atZone(zoneid)); + date += DateTimeFormatter.ofPattern(" (zzzz)", cx.getLocale()) + .format(Instant.ofEpochMilli(getLastModified()).atZone(zoneid)); + return date; } /** diff --git a/src/main/java/org/htmlunit/javascript/host/html/HTMLElement.java b/src/main/java/org/htmlunit/javascript/host/html/HTMLElement.java index e580725d1ae..cc1b4d4c064 100644 --- a/src/main/java/org/htmlunit/javascript/host/html/HTMLElement.java +++ b/src/main/java/org/htmlunit/javascript/host/html/HTMLElement.java @@ -1607,13 +1607,12 @@ public boolean isHidden() { * @param hidden the {@code hidden} value */ @JsxSetter - public void setHidden(final boolean hidden) { - if (hidden) { - getDomNodeOrDie().setAttribute("hidden", "hidden"); - } - else { - getDomNodeOrDie().removeAttribute("hidden"); + public void setHidden(final Object hidden) { + if (hidden instanceof Boolean) { + getDomNodeOrDie().setHidden((Boolean) hidden); + return; } + getDomNodeOrDie().setHidden(JavaScriptEngine.toString(hidden)); } /** diff --git a/src/main/java/org/htmlunit/javascript/host/html/HTMLTitleElement.java b/src/main/java/org/htmlunit/javascript/host/html/HTMLTitleElement.java index 3b601b3f738..ab7d927110a 100644 --- a/src/main/java/org/htmlunit/javascript/host/html/HTMLTitleElement.java +++ b/src/main/java/org/htmlunit/javascript/host/html/HTMLTitleElement.java @@ -14,8 +14,6 @@ */ package org.htmlunit.javascript.host.html; -import org.htmlunit.html.DomNode; -import org.htmlunit.html.DomText; import org.htmlunit.html.HtmlTitle; import org.htmlunit.javascript.configuration.JsxClass; import org.htmlunit.javascript.configuration.JsxConstructor; @@ -53,11 +51,8 @@ public void jsConstructor() { */ @JsxGetter public Object getText() { - final DomNode firstChild = getDomNodeOrDie().getFirstChild(); - if (firstChild != null) { - return firstChild.getNodeValue(); - } - return ""; + final HtmlTitle htmlTitle = (HtmlTitle) getDomNodeOrDie(); + return htmlTitle.getText(); } /** @@ -66,14 +61,7 @@ public Object getText() { */ @JsxSetter public void setText(final String text) { - final DomNode htmlElement = getDomNodeOrDie(); - DomNode firstChild = htmlElement.getFirstChild(); - if (firstChild == null) { - firstChild = new DomText(htmlElement.getPage(), text); - htmlElement.appendChild(firstChild); - } - else { - firstChild.setNodeValue(text); - } + final HtmlTitle htmlTitle = (HtmlTitle) getDomNodeOrDie(); + htmlTitle.setText(text); } } diff --git a/src/main/java/org/htmlunit/javascript/host/intl/DateTimeFormat.java b/src/main/java/org/htmlunit/javascript/host/intl/DateTimeFormat.java index f21623755ee..c9bf0f9bc98 100644 --- a/src/main/java/org/htmlunit/javascript/host/intl/DateTimeFormat.java +++ b/src/main/java/org/htmlunit/javascript/host/intl/DateTimeFormat.java @@ -27,6 +27,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import org.apache.commons.lang3.StringUtils; import org.htmlunit.BrowserVersion; import org.htmlunit.corejs.javascript.Context; import org.htmlunit.corejs.javascript.Function; @@ -69,7 +70,7 @@ public class DateTimeFormat extends HtmlUnitScriptable { final String yyyyDotBlankDot = "\u200EYYYY\u200E. \u200EMM\u200E. \u200Edd."; final Map commonFormats = new HashMap<>(); - commonFormats.put("", mmSlash); + commonFormats.put("", ddDot); commonFormats.put("ar", "dd\u200F/MM\u200F/YYYY"); commonFormats.put("ar-SA", "d\u200F/M\u200F/YYYY هـ"); commonFormats.put("ban", mmSlash); @@ -80,6 +81,7 @@ public class DateTimeFormat extends HtmlUnitScriptable { commonFormats.put("da", ddDot); commonFormats.put("de", ddDot); commonFormats.put("el", ddSlash); + commonFormats.put("en", mmSlash); commonFormats.put("en-CA", yyyyDash); commonFormats.put("en-NZ", ddSlash); commonFormats.put("en-PA", ddSlash); @@ -173,8 +175,8 @@ else if (browserVersion.isFirefoxESR()) { formats = FF_FORMATS_; } - String locale = ""; - String pattern = null; + String locale = browserVersion.getBrowserLocale().toLanguageTag(); + String pattern = getPattern(formats, locale); for (final String l : locales) { pattern = getPattern(formats, l); @@ -186,6 +188,7 @@ else if (browserVersion.isFirefoxESR()) { if (pattern == null) { pattern = formats.get(""); } + if (!locale.startsWith("ar")) { pattern = pattern.replace("\u200E", ""); } @@ -230,8 +233,9 @@ public static Scriptable jsConstructor(final Context cx, final Scriptable scope, } } else { - locales = new String[] {""}; + locales = new String[0]; } + final Window window = getWindow(ctorObj); final DateTimeFormat format = new DateTimeFormat(locales, window.getBrowserVersion()); format.setParentScope(window); @@ -247,7 +251,7 @@ public static Scriptable jsConstructor(final Context cx, final Scriptable scope, @JsxFunction public String format(final Object object) { final Date date = (Date) Context.jsToJava(object, Date.class); - return formatter_.format(date); + return formatter_.format(date, Context.getCurrentContext().getTimeZone().toZoneId()); } /** @@ -256,7 +260,17 @@ public String format(final Object object) { */ @JsxFunction public Scriptable resolvedOptions() { - return Context.getCurrentContext().newObject(getParentScope()); + final Context cx = Context.getCurrentContext(); + final Scriptable options = cx.newObject(getParentScope()); + options.put("timeZone", options, cx.getTimeZone().getID()); + + if (StringUtils.isEmpty(formatter_.locale_)) { + options.put("locale", options, cx.getLocale().toLanguageTag()); + } + else { + options.put("locale", options, formatter_.locale_); + } + return options; } /** @@ -266,8 +280,10 @@ static final class DateTimeFormatHelper { private final DateTimeFormatter formatter_; private Chronology chronology_; + private String locale_; DateTimeFormatHelper(final String locale, final BrowserVersion browserVersion, final String pattern) { + locale_ = locale; if (locale.startsWith("ar") && (!"ar-DZ".equals(locale) && !"ar-LY".equals(locale) @@ -301,10 +317,11 @@ static final class DateTimeFormatHelper { /** * Formats a date according to the locale and formatting options of this {@code DateTimeFormat} object. * @param date the JavaScript object to convert + * @param cx the current context * @return the dated formated */ - String format(final Date date) { - TemporalAccessor zonedDateTime = date.toInstant().atZone(ZoneId.systemDefault()); + String format(final Date date, final ZoneId zoneId) { + TemporalAccessor zonedDateTime = date.toInstant().atZone(zoneId); if (chronology_ != null) { zonedDateTime = chronology_.date(zonedDateTime); } diff --git a/src/site/xdoc/index.xml b/src/site/xdoc/index.xml index 4fef4a595b7..7cd4e7b110c 100644 --- a/src/site/xdoc/index.xml +++ b/src/site/xdoc/index.xml @@ -67,9 +67,9 @@

-
Latest release June 05, 2024
+
Latest release June 27, 2024
-

version 4.2.0

+

version 4.3.0

Source code
@@ -194,7 +194,7 @@ org.htmlunit htmlunit - 4.2.0 + 4.3.0 ]]>

@@ -237,6 +237,7 @@
  • MochiKit 1.4.2: Full support (see unit tests here)
  • GWT 2.5.0: Full support (see unit test here)
  • Sarissa 0.9.9.3: Full support (see unit test here)
  • +
  • Sarissa 0.9.9.7: Full support (see unit test here)
  • MooTools 1.2.1: Full support (see unit test here)
  • Prototype 1.7.1 (1.6.0, 1.6.1): Full support (see unit test here)
  • Ext JS 2.2: Very good support (see unit test here)
  • diff --git a/src/site/xdoc/webclient.xml b/src/site/xdoc/webclient.xml index aa571009ecb..66c50d7c1e7 100644 --- a/src/site/xdoc/webclient.xml +++ b/src/site/xdoc/webclient.xml @@ -35,8 +35,7 @@ try (final WebClient webClient = new WebClient()) {

    Often you will want to simulate a specific browser. This is done by passing a org.htmlunit.BrowserVersion into the WebClient constructor. - Constants have been provided for some common browsers, but you can create your own specific - version by instantiating a BrowserVersion. + Constants have been provided for some common browsers.

    - Specifying this BrowserVersion will change the user agent header that is sent up to the - server and will change the behavior of some of the JavaScript. + Specifying this BrowserVersion will change +

      +
    • the user agent HTTP header,
    • +
    • the values and the order of many other HTTP headers,
    • +
    • the list of supported mime types,
    • +
    • the behavior of the web client,
    • +
    • the supported javascript methods and and also the behaviour of some js functions,
    • +
    • the behavior of the web client, and
    • +
    • the default values for various css properties
    • +
    + to match the real browsers.

    -
    -
    -

    - There are various options available to make fine grained adjustments to the browser. -

    - In most cases, it should be sufficient to use the predefined BrowserVersion constants.

    + + +

    + There are various options available to make fine grained adjustments to the browser. +

    + -

    - The default values for most options are similar to the default values - of real browsers - but (as always) there is one important exception:
    - HtmlUnit stops the Javascript execution at the first unhandled exception - - Browsers do not stop. You can change this by changing the throwExceptionOnScriptError - option to false. -

    - + The default values for most options are similar to the default values + of real browsers - but (as always) there is one important exception:
    + HtmlUnit stops the Javascript execution at the first unhandled exception - + Browsers do not stop. You can change this by changing the throwExceptionOnScriptError + option to false. +

    + -

    - For a complete list and more details please have a look at the - WebClientOptions API. -

    +

    + For a complete list and more details please have a look at the + WebClientOptions API. +

    +
    + + +

    + Changing the language/time zone cannot be done from the options, it must be done before the WebClient is created.
    + All Browser Versions are shipped with 'en-US' as language and 'America/New_York' as timezone.
    + To change these default settings, a customised copy of the corresponding BrowserVersion must be created using the + BrowserVersionBuilder. This new BrowserVersion can then be used to create a WebClient. +

    + +

    + There is no support for changing the language/timezone after the WebClient has been created.
    + For more details please have a look at the + BrowserVersion.BrowserVersionBuilder API. +

    +
    diff --git a/src/test/java/org/htmlunit/BrowserVersionTest.java b/src/test/java/org/htmlunit/BrowserVersionTest.java index c01a2a83249..c719cdf1b91 100644 --- a/src/test/java/org/htmlunit/BrowserVersionTest.java +++ b/src/test/java/org/htmlunit/BrowserVersionTest.java @@ -38,10 +38,10 @@ public class BrowserVersionTest { */ @Test public void getBrowserVersionNumeric() { - assertEquals(126, BrowserVersion.FIREFOX.getBrowserVersionNumeric()); + assertEquals(127, BrowserVersion.FIREFOX.getBrowserVersionNumeric()); assertEquals(115, BrowserVersion.FIREFOX_ESR.getBrowserVersionNumeric()); - assertEquals(125, BrowserVersion.CHROME.getBrowserVersionNumeric()); - assertEquals(125, BrowserVersion.EDGE.getBrowserVersionNumeric()); + assertEquals(126, BrowserVersion.CHROME.getBrowserVersionNumeric()); + assertEquals(126, BrowserVersion.EDGE.getBrowserVersionNumeric()); } /** diff --git a/src/test/java/org/htmlunit/ExternalTest.java b/src/test/java/org/htmlunit/ExternalTest.java index 2668843647d..33397d9ef00 100644 --- a/src/test/java/org/htmlunit/ExternalTest.java +++ b/src/test/java/org/htmlunit/ExternalTest.java @@ -54,11 +54,11 @@ public class ExternalTest { static String MAVEN_REPO_URL_ = "https://repo1.maven.org/maven2/"; /** Chrome driver. */ - static String CHROME_DRIVER_ = "125.0.6422"; + static String CHROME_DRIVER_ = "126.0.6478"; static String CHROME_DRIVER_URL_ = "https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions-with-downloads.json"; - static String EDGE_DRIVER_ = "125.0.2535"; + static String EDGE_DRIVER_ = "126.0.2592"; static String EDGE_DRIVER_URL_ = "https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/"; /** Gecko driver. */ @@ -340,7 +340,8 @@ private static boolean isIgnored(@SuppressWarnings("unused") final String groupI // pmd 7 has problems parsing our code if ("maven-pmd-plugin".equals(artifactId) - && ("3.22.0".equals(version))) { + && ("3.22.0".equals(version) + || "3.23.0".equals(version))) { return true; } System.out.println(artifactId + " " + version); diff --git a/src/test/java/org/htmlunit/WebClient3Test.java b/src/test/java/org/htmlunit/WebClient3Test.java index 737b69495a7..a91a4a70389 100644 --- a/src/test/java/org/htmlunit/WebClient3Test.java +++ b/src/test/java/org/htmlunit/WebClient3Test.java @@ -29,6 +29,7 @@ import org.htmlunit.html.HtmlInlineFrame; import org.htmlunit.junit.BrowserRunner; import org.htmlunit.junit.BrowserRunner.Alerts; +import org.htmlunit.junit.BrowserRunner.HtmlUnitNYI; import org.htmlunit.junit.BrowserRunner.NotYetImplemented; import org.htmlunit.util.MimeType; import org.htmlunit.util.NameValuePair; @@ -581,4 +582,64 @@ private void encodingCharset(final String title, assertEquals(title, driver.getTitle()); } } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"en-US", "en-US,en"}) + public void language() throws Exception { + final String html + = "\n" + + ""; + + shutDownAll(); + try { + loadPageVerifyTitle2(html); + } + finally { + shutDownAll(); + } + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = {"de-DE", "de-DE,de,en-US,en"}, + FF = {"de-DE", "de-DE,de"}, + FF_ESR = {"de-DE", "de-DE,de"}) + @HtmlUnitNYI(CHROME = {"de-DE", "de-DE,de"}, + EDGE = {"de-DE", "de-DE,de"}) + public void languageDE() throws Exception { + final String html + = "\n" + + ""; + + shutDownAll(); + try { + final BrowserVersion.BrowserVersionBuilder builder + = new BrowserVersion.BrowserVersionBuilder(getBrowserVersion()); + builder.setBrowserLanguage("de-DE"); + builder.setAcceptLanguageHeader("de-DE,de"); + setBrowserVersion(builder.build()); + + loadPageVerifyTitle2(html); + } + finally { + shutDownAll(); + } + } } diff --git a/src/test/java/org/htmlunit/WebClient8Test.java b/src/test/java/org/htmlunit/WebClient8Test.java index d720fa0e728..5d3de29667f 100644 --- a/src/test/java/org/htmlunit/WebClient8Test.java +++ b/src/test/java/org/htmlunit/WebClient8Test.java @@ -396,4 +396,22 @@ public void imageEventHandlersWithNoJs() throws Exception { loadPage(webClient, html, null, URL_FIRST); } } + + /** + * @throws Exception if something goes wrong + */ + @Test + public void clickWithNoJs() throws Exception { + final String html = "\n" + + "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + ""; + + try (WebClient webClient = new WebClient(getBrowserVersion(), false, null, -1)) { + loadPage(webClient, html, null, URL_FIRST); + } + } } diff --git a/src/test/java/org/htmlunit/WebDriverTestCase.java b/src/test/java/org/htmlunit/WebDriverTestCase.java index 5cc63a10315..e3eaa0e5c64 100644 --- a/src/test/java/org/htmlunit/WebDriverTestCase.java +++ b/src/test/java/org/htmlunit/WebDriverTestCase.java @@ -89,6 +89,8 @@ import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.chrome.ChromeDriverService; import org.openqa.selenium.chrome.ChromeOptions; +import org.openqa.selenium.devtools.DevTools; +import org.openqa.selenium.devtools.v85.emulation.Emulation; import org.openqa.selenium.edge.EdgeDriver; import org.openqa.selenium.edge.EdgeDriverService; import org.openqa.selenium.edge.EdgeOptions; @@ -490,7 +492,7 @@ public void setUseStandards(final boolean useStandards) { */ protected WebDriver buildWebDriver() throws IOException { if (useRealBrowser()) { - if (BrowserVersion.EDGE == getBrowserVersion()) { + if (BrowserVersion.EDGE.isSameBrowser(getBrowserVersion())) { final EdgeDriverService service = new EdgeDriverService.Builder() .withLogOutput(System.out) .usingDriverExecutable(new File(EDGE_BIN_)) @@ -500,14 +502,24 @@ protected WebDriver buildWebDriver() throws IOException { .build(); + final String locale = getBrowserVersion().getBrowserLocale().toLanguageTag(); + final EdgeOptions options = new EdgeOptions(); - // options.addArguments("--lang=en-US"); - // options.addArguments("--remote-allow-origins=*"); + options.addArguments("--lang=" + locale); + options.addArguments("--remote-allow-origins=*"); + + final EdgeDriver edge = new EdgeDriver(service, options); + + final DevTools devTools = edge.getDevTools(); + devTools.createSession(); - return new EdgeDriver(service, options); + final String tz = getBrowserVersion().getSystemTimezone().getID(); + devTools.send(Emulation.setTimezoneOverride(tz)); + + return edge; } - if (BrowserVersion.CHROME == getBrowserVersion()) { + if (BrowserVersion.CHROME.isSameBrowser(getBrowserVersion())) { final ChromeDriverService service = new ChromeDriverService.Builder() .withLogOutput(System.out) .usingDriverExecutable(new File(CHROME_BIN_)) @@ -517,18 +529,28 @@ protected WebDriver buildWebDriver() throws IOException { .build(); + final String locale = getBrowserVersion().getBrowserLocale().toLanguageTag(); + final ChromeOptions options = new ChromeOptions(); - options.addArguments("--lang=en-US"); + options.addArguments("--lang=" + locale); options.addArguments("--remote-allow-origins=*"); - return new ChromeDriver(service, options); + final ChromeDriver chrome = new ChromeDriver(service, options); + + final DevTools devTools = chrome.getDevTools(); + devTools.createSession(); + + final String tz = getBrowserVersion().getSystemTimezone().getID(); + devTools.send(Emulation.setTimezoneOverride(tz)); + + return chrome; } - if (BrowserVersion.FIREFOX == getBrowserVersion()) { + if (BrowserVersion.FIREFOX.isSameBrowser(getBrowserVersion())) { return createFirefoxDriver(GECKO_BIN_, FF_BIN_); } - if (BrowserVersion.FIREFOX_ESR == getBrowserVersion()) { + if (BrowserVersion.FIREFOX_ESR.isSameBrowser(getBrowserVersion())) { return createFirefoxDriver(GECKO_BIN_, FF_ESR_BIN_); } @@ -536,13 +558,17 @@ protected WebDriver buildWebDriver() throws IOException { } if (webDriver_ == null) { + + final BrowserVersion browserVersion = getBrowserVersion(); + final DesiredCapabilities capabilities = new DesiredCapabilities(); capabilities.setBrowserName(Browser.HTMLUNIT.browserName()); - capabilities.setVersion(getBrowserName(getBrowserVersion())); + capabilities.setVersion(getBrowserName(browserVersion)); + webDriver_ = new HtmlUnitDriver(capabilities) { @Override protected WebClient newWebClient(final BrowserVersion version) { - final WebClient webClient = super.newWebClient(version); + final WebClient webClient = super.newWebClient(browserVersion); if (isWebClientCached()) { webClient.getOptions().setHistorySizeLimit(0); } @@ -559,7 +585,7 @@ protected WebClient newWebClient(final BrowserVersion version) { return webDriver_; } - private static FirefoxDriver createFirefoxDriver(final String geckodriverBinary, final String binary) { + private FirefoxDriver createFirefoxDriver(final String geckodriverBinary, final String binary) { final FirefoxDriverService service = new GeckoDriverService.Builder() .withLogOutput(System.out) .usingDriverExecutable(new File(geckodriverBinary)) @@ -568,9 +594,17 @@ private static FirefoxDriver createFirefoxDriver(final String geckodriverBinary, final FirefoxOptions options = new FirefoxOptions(); options.setBinary(binary); + final String tz = getBrowserVersion().getSystemTimezone().getID(); + + String locale = getBrowserVersion().getBrowserLocale().toLanguageTag(); + locale = locale + "," + getBrowserVersion().getBrowserLocale().getLanguage(); + final FirefoxProfile profile = new FirefoxProfile(); - profile.setPreference("intl.accept_languages", "en-US,en"); + profile.setPreference("intl.accept_languages", locale); + // no idea so far how to set this + // profile.setPreference("intl.tz", tz); options.setProfile(profile); + return new FirefoxDriver(service, options); } diff --git a/src/test/java/org/htmlunit/general/ElementDefaultStyleDisplayTest.java b/src/test/java/org/htmlunit/general/ElementDefaultStyleDisplayTest.java index da4f669a9e9..d20b883a715 100644 --- a/src/test/java/org/htmlunit/general/ElementDefaultStyleDisplayTest.java +++ b/src/test/java/org/htmlunit/general/ElementDefaultStyleDisplayTest.java @@ -940,7 +940,6 @@ public void meter() throws Exception { */ @Test @Alerts(DEFAULT = {"", "inline"}, - FF = {"", "block"}, FF_ESR = {"", "block"}) public void multicol() throws Exception { test("multicol"); diff --git a/src/test/java/org/htmlunit/general/ElementOwnPropertiesTest.java b/src/test/java/org/htmlunit/general/ElementOwnPropertiesTest.java index 8c3e50e2685..4a238b6cea5 100644 --- a/src/test/java/org/htmlunit/general/ElementOwnPropertiesTest.java +++ b/src/test/java/org/htmlunit/general/ElementOwnPropertiesTest.java @@ -40,6 +40,7 @@ import org.htmlunit.javascript.host.css.ComputedCSSStyleDeclaration; import org.htmlunit.javascript.host.dom.CDATASection; import org.htmlunit.javascript.host.dom.NodeList; +import org.htmlunit.javascript.host.dom.XPathEvaluator; import org.htmlunit.javascript.host.dom.XPathResult; import org.htmlunit.javascript.host.html.HTMLCollection; import org.htmlunit.javascript.host.performance.Performance; @@ -85,7 +86,7 @@ private void testString(final String preparation, final String string) throws Ex + " var div = document.createElement('div');\n" + " var svg = document.getElementById('mySvg');\n" + " try{\n" - + " " + preparation + "\n" + + " " + preparation + "\n" + " process(" + string + ");\n" + " } catch (e) {\n" + " log('exception');\n" @@ -106,10 +107,11 @@ private void testString(final String preparation, final String string) throws Ex // TODO remove if fixed in Rhino + " if ('__proto__' == property) continue;\n" - + " if (typeof object[property] == 'function') {\n" + + + " let desc = Object.getOwnPropertyDescriptor(object.constructor.prototype, property);\n" + + " if (desc.get === undefined && typeof object[property] == 'function') {\n" + " all.push(property + '()');\n" + " } else {\n" - + " let desc = Object.getOwnPropertyDescriptor(object.constructor.prototype, property);\n" + " property += '[';\n" + " if (desc.get != undefined) property += 'G';\n" + " if (desc.set != undefined) property += 'S';\n" @@ -935,7 +937,7 @@ public void event() throws Exception { + "ondragenter[GSCE],ondragleave[GSCE],ondragover[GSCE],ondragstart[GSCE],ondrop[GSCE]," + "ondurationchange[GSCE],onemptied[GSCE],onended[GSCE],onerror[GSCE],onfocus[GSCE]," + "ongotpointercapture[GSCE],onhashchange[GSCE],oninput[GSCE],oninvalid[GSCE],onkeydown[GSCE]," - + "onkeypress[GSCE],onkeyup[GSCE],onlanguagechange[GSCE],onload(),onloadeddata[GSCE]," + + "onkeypress[GSCE],onkeyup[GSCE],onlanguagechange[GSCE],onload[GSCE],onloadeddata[GSCE]," + "onloadedmetadata[GSCE],onloadstart[GSCE],onlostpointercapture[GSCE],onmessage[GSCE]," + "onmousedown[GSCE],onmouseenter[GSCE],onmouseleave[GSCE],onmousemove[GSCE],onmouseout[GSCE]," + "onmouseover[GSCE],onmouseup[GSCE],onmousewheel[GSCE],onoffline[GSCE],ononline[GSCE]," @@ -966,7 +968,7 @@ public void event() throws Exception { + "ondragenter[GSCE],ondragleave[GSCE],ondragover[GSCE],ondragstart[GSCE],ondrop[GSCE]," + "ondurationchange[GSCE],onemptied[GSCE],onended[GSCE],onerror[GSCE],onfocus[GSCE]," + "ongotpointercapture[GSCE],onhashchange[GSCE],oninput[GSCE],oninvalid[GSCE],onkeydown[GSCE]," - + "onkeypress[GSCE],onkeyup[GSCE],onlanguagechange[GSCE],onload(),onloadeddata[GSCE]," + + "onkeypress[GSCE],onkeyup[GSCE],onlanguagechange[GSCE],onload[GSCE],onloadeddata[GSCE]," + "onloadedmetadata[GSCE],onloadstart[GSCE],onlostpointercapture[GSCE],onmessage[GSCE]," + "onmousedown[GSCE],onmouseenter[GSCE],onmouseleave[GSCE],onmousemove[GSCE],onmouseout[GSCE]," + "onmouseover[GSCE],onmouseup[GSCE],onmousewheel[GSCE],onoffline[GSCE],ononline[GSCE]," @@ -998,7 +1000,7 @@ public void event() throws Exception { + "ondeviceorientation[GSCE],ondrag[GSCE],ondragend[GSCE],ondragenter[GSCE]," + "ondragleave[GSCE],ondragover[GSCE],ondragstart[GSCE],ondrop[GSCE],ondurationchange[GSCE]," + "onemptied[GSCE],onended[GSCE],onerror[GSCE],onfocus[GSCE],onhashchange[GSCE],oninput[GSCE]," - + "oninvalid[GSCE],onkeydown[GSCE],onkeypress[GSCE],onkeyup[GSCE],onlanguagechange[GSCE],onload()," + + "oninvalid[GSCE],onkeydown[GSCE],onkeypress[GSCE],onkeyup[GSCE],onlanguagechange[GSCE],onload[GSCE]," + "onloadeddata[GSCE],onloadedmetadata[GSCE],onloadstart[GSCE],onmessage[GSCE],onmousedown[GSCE]," + "onmouseenter[GSCE],onmouseleave[GSCE],onmousemove[GSCE],onmouseout[GSCE],onmouseover[GSCE]," + "onmouseup[GSCE],onmozfullscreenchange[GSCE],onmozfullscreenerror[GSCE],onoffline[GSCE]," @@ -1025,7 +1027,7 @@ public void event() throws Exception { + "ondeviceorientation[GSCE],ondrag[GSCE],ondragend[GSCE],ondragenter[GSCE]," + "ondragleave[GSCE],ondragover[GSCE],ondragstart[GSCE],ondrop[GSCE],ondurationchange[GSCE]," + "onemptied[GSCE],onended[GSCE],onerror[GSCE],onfocus[GSCE],onhashchange[GSCE],oninput[GSCE]," - + "oninvalid[GSCE],onkeydown[GSCE],onkeypress[GSCE],onkeyup[GSCE],onlanguagechange[GSCE],onload()," + + "oninvalid[GSCE],onkeydown[GSCE],onkeypress[GSCE],onkeyup[GSCE],onlanguagechange[GSCE],onload[GSCE]," + "onloadeddata[GSCE],onloadedmetadata[GSCE],onloadstart[GSCE],onmessage[GSCE],onmousedown[GSCE]," + "onmouseenter[GSCE],onmouseleave[GSCE],onmousemove[GSCE],onmouseout[GSCE],onmouseover[GSCE]," + "onmouseup[GSCE],onmozfullscreenchange[GSCE],onmozfullscreenerror[GSCE],onoffline[GSCE]," @@ -3269,14 +3271,14 @@ public void blockquote() throws Exception { @Test @Alerts(CHROME = "aLink[GSCE],background[GSCE],bgColor[GSCE],constructor(),link[GSCE],onafterprint[GSCE]," + "onbeforeprint[GSCE],onbeforeunload[GSCE],onblur[GSCE],onerror[GSCE],onfocus[GSCE]," - + "onhashchange[GSCE],onlanguagechange[GSCE],onload(),onmessage[GSCE],onmessageerror[GSCE]," + + "onhashchange[GSCE],onlanguagechange[GSCE],onload[GSCE],onmessage[GSCE],onmessageerror[GSCE]," + "onoffline[GSCE],ononline[GSCE],onpagehide[GSCE],onpageshow[GSCE],onpopstate[GSCE]," + "onrejectionhandled[GSCE],onresize[GSCE],onscroll[GSCE],onstorage[GSCE]," + "onunhandledrejection[GSCE],onunload[GSCE],text[GSCE]," + "vLink[GSCE]", EDGE = "aLink[GSCE],background[GSCE],bgColor[GSCE],constructor(),link[GSCE],onafterprint[GSCE]," + "onbeforeprint[GSCE],onbeforeunload[GSCE],onblur[GSCE],onerror[GSCE],onfocus[GSCE]," - + "onhashchange[GSCE],onlanguagechange[GSCE],onload(),onmessage[GSCE],onmessageerror[GSCE]," + + "onhashchange[GSCE],onlanguagechange[GSCE],onload[GSCE],onmessage[GSCE],onmessageerror[GSCE]," + "onoffline[GSCE],ononline[GSCE],onpagehide[GSCE],onpageshow[GSCE],onpopstate[GSCE]," + "onrejectionhandled[GSCE],onresize[GSCE],onscroll[GSCE],onstorage[GSCE]," + "onunhandledrejection[GSCE],onunload[GSCE],text[GSCE]," @@ -6118,13 +6120,13 @@ public void frame() throws Exception { */ @Test @Alerts(CHROME = "cols[GSCE],constructor(),onafterprint[GSCE],onbeforeprint[GSCE],onbeforeunload[GSCE]," - + "onblur[GSCE],onerror[GSCE],onfocus[GSCE],onhashchange[GSCE],onlanguagechange[GSCE],onload()," + + "onblur[GSCE],onerror[GSCE],onfocus[GSCE],onhashchange[GSCE],onlanguagechange[GSCE],onload[GSCE]," + "onmessage[GSCE],onmessageerror[GSCE],onoffline[GSCE],ononline[GSCE],onpagehide[GSCE]," + "onpageshow[GSCE],onpopstate[GSCE],onrejectionhandled[GSCE],onresize[GSCE],onscroll[GSCE]," + "onstorage[GSCE],onunhandledrejection[GSCE],onunload[GSCE]," + "rows[GSCE]", EDGE = "cols[GSCE],constructor(),onafterprint[GSCE],onbeforeprint[GSCE],onbeforeunload[GSCE]," - + "onblur[GSCE],onerror[GSCE],onfocus[GSCE],onhashchange[GSCE],onlanguagechange[GSCE],onload()," + + "onblur[GSCE],onerror[GSCE],onfocus[GSCE],onhashchange[GSCE],onlanguagechange[GSCE],onload[GSCE]," + "onmessage[GSCE],onmessageerror[GSCE],onoffline[GSCE],ononline[GSCE],onpagehide[GSCE]," + "onpageshow[GSCE],onpopstate[GSCE],onrejectionhandled[GSCE],onresize[GSCE],onscroll[GSCE]," + "onstorage[GSCE],onunhandledrejection[GSCE],onunload[GSCE]," @@ -6514,16 +6516,18 @@ public void html() throws Exception { */ @Test @Alerts(CHROME = "adAuctionHeaders[GSCE],align[GSCE],allow[GSCE],allowFullscreen[GSCE],allowPaymentRequest[GSCE]," - + "constructor(),contentDocument[GCE],contentWindow[GCE],credentialless[GSCE],csp[GSCE]," - + "featurePolicy[GCE],frameBorder[GSCE],getSVGDocument(),height[GSCE],loading[GSCE],longDesc[GSCE]," - + "marginHeight[GSCE],marginWidth[GSCE],name[GSCE],privateToken[GSCE],referrerPolicy[GSCE]," - + "sandbox[GSCE],scrolling[GSCE],sharedStorageWritable[GSCE],src[GSCE],srcdoc[GSCE]," + + "browsingTopics[GSCE],constructor(),contentDocument[GCE],contentWindow[GCE],credentialless[GSCE]," + + "csp[GSCE],featurePolicy[GCE],frameBorder[GSCE],getSVGDocument(),height[GSCE],loading[GSCE]," + + "longDesc[GSCE],marginHeight[GSCE],marginWidth[GSCE],name[GSCE],privateToken[GSCE]," + + "referrerPolicy[GSCE],sandbox[GSCE],scrolling[GSCE],sharedStorageWritable[GSCE],src[GSCE]," + + "srcdoc[GSCE]," + "width[GSCE]", EDGE = "adAuctionHeaders[GSCE],align[GSCE],allow[GSCE],allowFullscreen[GSCE],allowPaymentRequest[GSCE]," - + "constructor(),contentDocument[GCE],contentWindow[GCE],credentialless[GSCE],csp[GSCE]," - + "featurePolicy[GCE],frameBorder[GSCE],getSVGDocument(),height[GSCE],loading[GSCE],longDesc[GSCE]," - + "marginHeight[GSCE],marginWidth[GSCE],name[GSCE],privateToken[GSCE],referrerPolicy[GSCE]," - + "sandbox[GSCE],scrolling[GSCE],sharedStorageWritable[GSCE],src[GSCE],srcdoc[GSCE]," + + "browsingTopics[GSCE],constructor(),contentDocument[GCE],contentWindow[GCE],credentialless[GSCE]," + + "csp[GSCE],featurePolicy[GCE],frameBorder[GSCE],getSVGDocument(),height[GSCE],loading[GSCE]," + + "longDesc[GSCE],marginHeight[GSCE],marginWidth[GSCE],name[GSCE],privateToken[GSCE]," + + "referrerPolicy[GSCE],sandbox[GSCE],scrolling[GSCE],sharedStorageWritable[GSCE],src[GSCE]," + + "srcdoc[GSCE]," + "width[GSCE]", FF = "align[GSCE],allow[GSCE],allowFullscreen[GSCE],constructor(),contentDocument[GCE]," + "contentWindow[GCE],frameBorder[GSCE],getSVGDocument(),height[GSCE],loading[GSCE],longDesc[GSCE]," @@ -13781,17 +13785,13 @@ public void var() throws Exception { @Alerts(CHROME = "cancelVideoFrameCallback(),constructor(),disablePictureInPicture[GSCE],getVideoPlaybackQuality()," + "height[GSCE],onenterpictureinpicture[GSCE],onleavepictureinpicture[GSCE],playsInline[GSCE]," + "poster[GSCE],requestPictureInPicture(),requestVideoFrameCallback(),videoHeight[GCE]," - + "videoWidth[GCE],webkitDecodedFrameCount[GCE],webkitDisplayingFullscreen[GCE]," - + "webkitDroppedFrameCount[GCE],webkitEnterFullScreen(),webkitEnterFullscreen()," - + "webkitExitFullScreen(),webkitExitFullscreen(),webkitSupportsFullscreen[GCE]," + + "videoWidth[GCE],webkitDecodedFrameCount[GCE],webkitDroppedFrameCount[GCE]," + "width[GSCE]", EDGE = "cancelVideoFrameCallback(),constructor(),disablePictureInPicture[GSCE],getVideoPlaybackQuality()," + "height[GSCE],msGetVideoProcessingTypes(),msVideoProcessing[GSCE],onenterpictureinpicture[GSCE]," + "onleavepictureinpicture[GSCE],playsInline[GSCE],poster[GSCE],requestPictureInPicture()," + "requestVideoFrameCallback(),videoHeight[GCE],videoWidth[GCE],webkitDecodedFrameCount[GCE]," - + "webkitDisplayingFullscreen[GCE],webkitDroppedFrameCount[GCE],webkitEnterFullScreen()," - + "webkitEnterFullscreen(),webkitExitFullScreen(),webkitExitFullscreen()," - + "webkitSupportsFullscreen[GCE]," + + "webkitDroppedFrameCount[GCE]," + "width[GSCE]", FF = "constructor(),disablePictureInPicture[GSCE],getVideoPlaybackQuality(),height[GSCE]," + "mozDecodedFrames[GCE],mozFrameDelay[GCE],mozHasAudio[GCE],mozPaintedFrames[GCE]," @@ -14785,9 +14785,9 @@ public void slot() throws Exception { */ @Test @Alerts(CHROME = "activeElement[GCE],adoptedStyleSheets[GSCE],adoptNode(),alinkColor[GSCE],all[GCE],anchors[GCE]," - + "append(),applets[GCE],bgColor[GSCE],body[GSCE],captureEvents(),caretRangeFromPoint()," - + "characterSet[GCE],charset[GCE],childElementCount[GCE],children[GCE],clear(),close()," - + "compatMode[GCE],constructor(),contentType[GCE],cookie[GSCE],createAttribute()," + + "append(),applets[GCE],bgColor[GSCE],body[GSCE],browsingTopics(),captureEvents()," + + "caretRangeFromPoint(),characterSet[GCE],charset[GCE],childElementCount[GCE],children[GCE]," + + "clear(),close(),compatMode[GCE],constructor(),contentType[GCE],cookie[GSCE],createAttribute()," + "createAttributeNS(),createCDATASection(),createComment(),createDocumentFragment()," + "createElement(),createElementNS(),createEvent(),createExpression(),createNodeIterator()," + "createNSResolver(),createProcessingInstruction(),createRange(),createTextNode()," @@ -14838,9 +14838,9 @@ public void slot() throws Exception { + "xmlStandalone[GSCE]," + "xmlVersion[GSCE]", EDGE = "activeElement[GCE],adoptedStyleSheets[GSCE],adoptNode(),alinkColor[GSCE],all[GCE],anchors[GCE]," - + "append(),applets[GCE],bgColor[GSCE],body[GSCE],captureEvents(),caretRangeFromPoint()," - + "characterSet[GCE],charset[GCE],childElementCount[GCE],children[GCE],clear(),close()," - + "compatMode[GCE],constructor(),contentType[GCE],cookie[GSCE],createAttribute()," + + "append(),applets[GCE],bgColor[GSCE],body[GSCE],browsingTopics(),captureEvents()," + + "caretRangeFromPoint(),characterSet[GCE],charset[GCE],childElementCount[GCE],children[GCE]," + + "clear(),close(),compatMode[GCE],constructor(),contentType[GCE],cookie[GSCE],createAttribute()," + "createAttributeNS(),createCDATASection(),createComment(),createDocumentFragment()," + "createElement(),createElementNS(),createEvent(),createExpression(),createNodeIterator()," + "createNSResolver(),createProcessingInstruction(),createRange(),createTextNode()," @@ -15287,14 +15287,6 @@ public void range() throws Exception { FF_ESR = "append(),childElementCount[GCE],children[GCE],constructor(),firstElementChild[GCE]," + "getElementById(),lastElementChild[GCE],prepend(),querySelector(),querySelectorAll()," + "replaceChildren()") - @HtmlUnitNYI(CHROME = "childElementCount[GCE],children[GCE],constructor(),firstElementChild[GCE]," - + "getElementById(),lastElementChild[GCE],querySelector(),querySelectorAll()", - EDGE = "childElementCount[GCE],children[GCE],constructor(),firstElementChild[GCE]," - + "getElementById(),lastElementChild[GCE],querySelector(),querySelectorAll()", - FF_ESR = "childElementCount[GCE],children[GCE],constructor(),firstElementChild[GCE]," - + "getElementById(),lastElementChild[GCE],querySelector(),querySelectorAll()", - FF = "childElementCount[GCE],children[GCE],constructor(),firstElementChild[GCE]," - + "getElementById(),lastElementChild[GCE],querySelector(),querySelectorAll()") public void documentFragment() throws Exception { testString("", "document.createDocumentFragment()"); } @@ -17105,16 +17097,64 @@ public void cryptoSubtle() throws Exception { testString("", "window.crypto.subtle"); } + /** + * Test {@link XPathEvaluator}. + * + * @throws Exception if the test fails + */ + @Test + @Alerts(CHROME = "constructor(),createExpression(),createNSResolver(),evaluate()", + EDGE = "constructor(),createExpression(),createNSResolver(),evaluate()", + FF = "constructor(),createExpression(),createNSResolver(),evaluate()", + FF_ESR = "constructor(),createExpression(),createNSResolver(),evaluate()") + public void xPathEvaluator() throws Exception { + testString("", "new XPathEvaluator()"); + } + + /** + * Test {@link XPathExpression}. + * + * @throws Exception if the test fails + */ + @Test + @Alerts(CHROME = "constructor(),evaluate()", + EDGE = "constructor(),evaluate()", + FF = "constructor(),evaluate()", + FF_ESR = "constructor(),evaluate()") + public void xPathExpression() throws Exception { + testString("var res = new XPathEvaluator().createExpression('//span')", "res"); + } + /** * Test {@link XPathResult}. * * @throws Exception if the test fails */ @Test - @Alerts(CHROME = "exception", - EDGE = "exception", - FF = "exception", - FF_ESR = "exception") + @Alerts(CHROME = "ANY_TYPE[E],ANY_UNORDERED_NODE_TYPE[E],BOOLEAN_TYPE[E],booleanValue[GCE],constructor()," + + "FIRST_ORDERED_NODE_TYPE[E],invalidIteratorState[GCE],iterateNext(),NUMBER_TYPE[E]," + + "numberValue[GCE],ORDERED_NODE_ITERATOR_TYPE[E],ORDERED_NODE_SNAPSHOT_TYPE[E],resultType[GCE]," + + "singleNodeValue[GCE],snapshotItem(),snapshotLength[GCE],STRING_TYPE[E],stringValue[GCE]," + + "UNORDERED_NODE_ITERATOR_TYPE[E]," + + "UNORDERED_NODE_SNAPSHOT_TYPE[E]", + EDGE = "ANY_TYPE[E],ANY_UNORDERED_NODE_TYPE[E],BOOLEAN_TYPE[E],booleanValue[GCE],constructor()," + + "FIRST_ORDERED_NODE_TYPE[E],invalidIteratorState[GCE],iterateNext(),NUMBER_TYPE[E]," + + "numberValue[GCE],ORDERED_NODE_ITERATOR_TYPE[E],ORDERED_NODE_SNAPSHOT_TYPE[E],resultType[GCE]," + + "singleNodeValue[GCE],snapshotItem(),snapshotLength[GCE],STRING_TYPE[E],stringValue[GCE]," + + "UNORDERED_NODE_ITERATOR_TYPE[E]," + + "UNORDERED_NODE_SNAPSHOT_TYPE[E]", + FF = "ANY_TYPE[E],ANY_UNORDERED_NODE_TYPE[E],BOOLEAN_TYPE[E],booleanValue[GCE],constructor()," + + "FIRST_ORDERED_NODE_TYPE[E],invalidIteratorState[GCE],iterateNext(),NUMBER_TYPE[E]," + + "numberValue[GCE],ORDERED_NODE_ITERATOR_TYPE[E],ORDERED_NODE_SNAPSHOT_TYPE[E],resultType[GCE]," + + "singleNodeValue[GCE],snapshotItem(),snapshotLength[GCE],STRING_TYPE[E],stringValue[GCE]," + + "UNORDERED_NODE_ITERATOR_TYPE[E]," + + "UNORDERED_NODE_SNAPSHOT_TYPE[E]", + FF_ESR = "ANY_TYPE[E],ANY_UNORDERED_NODE_TYPE[E],BOOLEAN_TYPE[E],booleanValue[GCE],constructor()," + + "FIRST_ORDERED_NODE_TYPE[E],invalidIteratorState[GCE],iterateNext(),NUMBER_TYPE[E]," + + "numberValue[GCE],ORDERED_NODE_ITERATOR_TYPE[E],ORDERED_NODE_SNAPSHOT_TYPE[E],resultType[GCE]," + + "singleNodeValue[GCE],snapshotItem(),snapshotLength[GCE],STRING_TYPE[E],stringValue[GCE]," + + "UNORDERED_NODE_ITERATOR_TYPE[E]," + + "UNORDERED_NODE_SNAPSHOT_TYPE[E]") public void xPathResult() throws Exception { testString("var res = document.evaluate('/html/body', document, null, XPathResult.ANY_TYPE, null);", "res"); } diff --git a/src/test/java/org/htmlunit/general/ElementOwnPropertySymbolsTest.java b/src/test/java/org/htmlunit/general/ElementOwnPropertySymbolsTest.java index 54af7f5f913..64b1911e8e3 100644 --- a/src/test/java/org/htmlunit/general/ElementOwnPropertySymbolsTest.java +++ b/src/test/java/org/htmlunit/general/ElementOwnPropertySymbolsTest.java @@ -40,6 +40,7 @@ import org.htmlunit.javascript.host.css.ComputedCSSStyleDeclaration; import org.htmlunit.javascript.host.dom.CDATASection; import org.htmlunit.javascript.host.dom.NodeList; +import org.htmlunit.javascript.host.dom.XPathEvaluator; import org.htmlunit.javascript.host.dom.XPathResult; import org.htmlunit.javascript.host.html.HTMLCollection; import org.htmlunit.javascript.host.performance.Performance; @@ -2839,6 +2840,28 @@ public void cryptoSubtle() throws Exception { testString("", "window.crypto.subtle"); } + /** + * Test {@link XPathEvaluator}. + * + * @throws Exception if the test fails + */ + @Test + @Alerts("Symbol(Symbol.toStringTag) [C] [XPathEvaluator]") + public void xPathEvaluator() throws Exception { + testString("", "new XPathEvaluator()"); + } + + /** + * Test {@link XPathExpression}. + * + * @throws Exception if the test fails + */ + @Test + @Alerts("Symbol(Symbol.toStringTag) [C] [XPathExpression]") + public void xPathExpression() throws Exception { + testString("var res = new XPathEvaluator().createExpression('//span')", "res"); + } + /** * Test {@link XPathResult}. * diff --git a/src/test/java/org/htmlunit/general/ElementPropertiesTest.java b/src/test/java/org/htmlunit/general/ElementPropertiesTest.java index 681b1722a83..3dfb9d909bb 100644 --- a/src/test/java/org/htmlunit/general/ElementPropertiesTest.java +++ b/src/test/java/org/htmlunit/general/ElementPropertiesTest.java @@ -39,6 +39,7 @@ import org.htmlunit.javascript.host.crypto.SubtleCrypto; import org.htmlunit.javascript.host.dom.CDATASection; import org.htmlunit.javascript.host.dom.NodeList; +import org.htmlunit.javascript.host.dom.XPathEvaluator; import org.htmlunit.javascript.host.dom.XPathResult; import org.htmlunit.javascript.host.html.HTMLCollection; import org.htmlunit.javascript.host.performance.Performance; @@ -854,58 +855,54 @@ public void element() throws Exception { + "setAttribute(),setAttributeNode(),setAttributeNodeNS(),setAttributeNS(),setCapture()," + "setPointerCapture(),shadowRoot,slot,tagName,toggleAttribute()," + "webkitMatchesSelector()") - @HtmlUnitNYI(CHROME = "after(),append(),attributes,before(),classList,className,clientHeight,clientLeft,clientTop," + @HtmlUnitNYI(CHROME = "after(),attributes,before(),classList,className,clientHeight,clientLeft,clientTop," + "clientWidth,closest(),getAttribute(),getAttributeNode(),getAttributeNodeNS(),getAttributeNS()," + "getBoundingClientRect(),getClientRects(),getElementsByClassName(),getElementsByTagName()," + "getElementsByTagNameNS(),getHTML(),getInnerHTML()," + "hasAttribute(),hasAttributeNS(),hasAttributes(),id,innerHTML," + "insertAdjacentElement(),insertAdjacentHTML(),insertAdjacentText(),localName,matches()," + "namespaceURI,nextElementSibling,onbeforecopy,onbeforecut,onbeforepaste," - + "onsearch,onwebkitfullscreenchange,onwebkitfullscreenerror,outerHTML,prefix,prepend()," + + "onsearch,onwebkitfullscreenchange,onwebkitfullscreenerror,outerHTML,prefix," + "previousElementSibling,remove(),removeAttribute(),removeAttributeNode(),removeAttributeNS()," - + "replaceChildren(),replaceWith()," - + "scroll(),scrollBy(),scrollHeight,scrollIntoView(),scrollIntoViewIfNeeded()," + + "replaceWith(),scroll(),scrollBy(),scrollHeight,scrollIntoView(),scrollIntoViewIfNeeded()," + "scrollLeft,scrollTo(),scrollTop," + "scrollWidth,setAttribute(),setAttributeNode(),setAttributeNS()," + "tagName,toggleAttribute(),webkitMatchesSelector()", - EDGE = "after(),append(),attributes,before(),classList,className,clientHeight,clientLeft,clientTop," + EDGE = "after(),attributes,before(),classList,className,clientHeight,clientLeft,clientTop," + "clientWidth,closest(),getAttribute(),getAttributeNode(),getAttributeNodeNS(),getAttributeNS()," + "getBoundingClientRect(),getClientRects(),getElementsByClassName(),getElementsByTagName()," + "getElementsByTagNameNS(),getHTML(),getInnerHTML()," + "hasAttribute(),hasAttributeNS(),hasAttributes(),id,innerHTML," + "insertAdjacentElement(),insertAdjacentHTML(),insertAdjacentText(),localName,matches()," + "namespaceURI,nextElementSibling,onbeforecopy,onbeforecut,onbeforepaste," - + "onsearch,onwebkitfullscreenchange,onwebkitfullscreenerror,outerHTML,prefix,prepend()," + + "onsearch,onwebkitfullscreenchange,onwebkitfullscreenerror,outerHTML,prefix," + "previousElementSibling,remove(),removeAttribute(),removeAttributeNode(),removeAttributeNS()," - + "replaceChildren(),replaceWith()," - + "scroll(),scrollBy(),scrollHeight,scrollIntoView(),scrollIntoViewIfNeeded()," + + "replaceWith(),scroll(),scrollBy(),scrollHeight,scrollIntoView(),scrollIntoViewIfNeeded()," + "scrollLeft,scrollTo(),scrollTop," + "scrollWidth,setAttribute(),setAttributeNode(),setAttributeNS()," + "tagName,toggleAttribute(),webkitMatchesSelector()", - FF_ESR = "after(),append(),attributes,before()," + FF_ESR = "after(),attributes,before()," + "classList,className,clientHeight,clientLeft,clientTop,clientWidth," + "closest(),getAttribute(),getAttributeNode(),getAttributeNodeNS(),getAttributeNS()," + "getBoundingClientRect()," + "getClientRects(),getElementsByClassName(),getElementsByTagName(),getElementsByTagNameNS()," + "hasAttribute(),hasAttributeNS(),hasAttributes(),id,innerHTML,insertAdjacentElement()," + "insertAdjacentHTML(),insertAdjacentText(),localName,matches(),mozMatchesSelector(),namespaceURI," - + "nextElementSibling,outerHTML,prefix,prepend(),previousElementSibling," + + "nextElementSibling,outerHTML,prefix,previousElementSibling," + "releaseCapture(),remove(),removeAttribute(),removeAttributeNode(),removeAttributeNS()," - + "replaceChildren(),replaceWith()," - + "scroll(),scrollBy(),scrollHeight," + + "replaceWith(),scroll(),scrollBy(),scrollHeight," + "scrollIntoView(),scrollLeft,scrollTo(),scrollTop,scrollWidth,setAttribute(),setAttributeNode()," + "setAttributeNS(),setCapture()," + "tagName,toggleAttribute(),webkitMatchesSelector()", - FF = "after(),append(),attributes,before()," + FF = "after(),attributes,before()," + "classList,className,clientHeight,clientLeft,clientTop,clientWidth," + "closest(),getAttribute(),getAttributeNode(),getAttributeNodeNS(),getAttributeNS()," + "getBoundingClientRect()," + "getClientRects(),getElementsByClassName(),getElementsByTagName(),getElementsByTagNameNS()," + "hasAttribute(),hasAttributeNS(),hasAttributes(),id,innerHTML,insertAdjacentElement()," + "insertAdjacentHTML(),insertAdjacentText(),localName,matches(),mozMatchesSelector(),namespaceURI," - + "nextElementSibling,outerHTML,prefix,prepend(),previousElementSibling," - + "releaseCapture(),remove()," - + "removeAttribute(),removeAttributeNode(),removeAttributeNS(),replaceChildren(),replaceWith()," + + "nextElementSibling,outerHTML,prefix,previousElementSibling,releaseCapture(),remove()," + + "removeAttribute(),removeAttributeNode(),removeAttributeNS(),replaceWith()," + "scroll(),scrollBy(),scrollHeight," + "scrollIntoView(),scrollLeft,scrollTo(),scrollTop,scrollWidth,setAttribute(),setAttributeNode()," + "setAttributeNS(),setCapture()," @@ -981,8 +978,8 @@ public void event() throws Exception { + "cdc_adoQpoasnfa76pfcZLmcfl_Promise(),cdc_adoQpoasnfa76pfcZLmcfl_Proxy()," + "cdc_adoQpoasnfa76pfcZLmcfl_Symbol(),chrome,clearInterval(),clearTimeout(),clientInformation," + "close(),closed,confirm(),cookieStore,createImageBitmap(),credentialless,crossOriginIsolated," - + "crypto,customElements,devicePixelRatio,dispatchEvent(),document,documentPictureInPicture," - + "external,fetch(),find(),focus(),frameElement,frames,getComputedStyle(),getScreenDetails()," + + "crypto,customElements,devicePixelRatio,dispatchEvent(),document,documentPictureInPicture,event," + + "external,fence,fetch(),find(),focus(),frameElement,frames,getComputedStyle(),getScreenDetails()," + "getSelection(),history,indexedDB,innerHeight,innerWidth,isSecureContext,launchQueue,length," + "localStorage,location,locationbar,log(),matchMedia(),menubar,moveBy(),moveTo(),name,navigation," + "navigator,onabort,onafterprint,onanimationend,onanimationiteration,onanimationstart," @@ -1008,9 +1005,9 @@ public void event() throws Exception { + "queueMicrotask(),releaseEvents(),removeEventListener(),reportError(),requestAnimationFrame()," + "requestIdleCallback(),resizeBy(),resizeTo(),scheduler,screen,screenLeft,screenTop,screenX," + "screenY,scroll(),scrollbars,scrollBy(),scrollTo(),scrollX,scrollY,self,sessionStorage," - + "setInterval(),setTimeout(),showDirectoryPicker(),showOpenFilePicker(),showSaveFilePicker()," - + "sortFunction(),speechSynthesis,status,statusbar,stop(),structuredClone(),styleMedia,TEMPORARY," - + "test(),toolbar,top,trustedTypes,visualViewport,webkitCancelAnimationFrame()," + + "setInterval(),setTimeout(),sharedStorage,showDirectoryPicker(),showOpenFilePicker()," + + "showSaveFilePicker(),sortFunction(),speechSynthesis,status,statusbar,stop(),structuredClone()," + + "styleMedia,TEMPORARY,test(),toolbar,top,trustedTypes,visualViewport,webkitCancelAnimationFrame()," + "webkitRequestAnimationFrame(),webkitRequestFileSystem(),webkitResolveLocalFileSystemURL()," + "window", EDGE = "addEventListener(),alert(),atob(),blur(),btoa(),caches,cancelAnimationFrame()," @@ -1019,8 +1016,8 @@ public void event() throws Exception { + "cdc_adoQpoasnfa76pfcZLmcfl_Promise(),cdc_adoQpoasnfa76pfcZLmcfl_Proxy()," + "cdc_adoQpoasnfa76pfcZLmcfl_Symbol(),chrome,clearInterval(),clearTimeout(),clientInformation," + "close(),closed,confirm(),cookieStore,createImageBitmap(),credentialless,crossOriginIsolated," - + "crypto,customElements,devicePixelRatio,dispatchEvent(),document,documentPictureInPicture," - + "external,fetch(),find(),focus(),frameElement,frames,getComputedStyle(),getScreenDetails()," + + "crypto,customElements,devicePixelRatio,dispatchEvent(),document,documentPictureInPicture,event," + + "external,fence,fetch(),find(),focus(),frameElement,frames,getComputedStyle(),getScreenDetails()," + "getSelection(),history,indexedDB,innerHeight,innerWidth,isSecureContext,launchQueue,length," + "localStorage,location,locationbar,log(),matchMedia(),menubar,moveBy(),moveTo(),name,navigation," + "navigator,onabort,onafterprint,onanimationend,onanimationiteration,onanimationstart," @@ -1046,9 +1043,9 @@ public void event() throws Exception { + "queueMicrotask(),releaseEvents(),removeEventListener(),reportError(),requestAnimationFrame()," + "requestIdleCallback(),resizeBy(),resizeTo(),scheduler,screen,screenLeft,screenTop,screenX," + "screenY,scroll(),scrollbars,scrollBy(),scrollTo(),scrollX,scrollY,self,sessionStorage," - + "setInterval(),setTimeout(),showDirectoryPicker(),showOpenFilePicker(),showSaveFilePicker()," - + "sortFunction(),speechSynthesis,status,statusbar,stop(),structuredClone(),styleMedia,TEMPORARY," - + "test(),toolbar,top,trustedTypes,visualViewport,webkitCancelAnimationFrame()," + + "setInterval(),setTimeout(),sharedStorage,showDirectoryPicker(),showOpenFilePicker()," + + "showSaveFilePicker(),sortFunction(),speechSynthesis,status,statusbar,stop(),structuredClone()," + + "styleMedia,TEMPORARY,test(),toolbar,top,trustedTypes,visualViewport,webkitCancelAnimationFrame()," + "webkitRequestAnimationFrame(),webkitRequestFileSystem(),webkitResolveLocalFileSystemURL()," + "window", FF = "addEventListener(),alert(),atob(),blur(),btoa(),caches,cancelAnimationFrame()," @@ -2041,14 +2038,14 @@ public void html() throws Exception { * @throws Exception if the test fails */ @Test - @Alerts(CHROME = "adAuctionHeaders,align,allow,allowFullscreen,allowPaymentRequest,contentDocument,contentWindow," - + "credentialless,csp,featurePolicy,frameBorder,getSVGDocument(),height,loading,longDesc," - + "marginHeight,marginWidth,name,privateToken,referrerPolicy,sandbox,scrolling," + @Alerts(CHROME = "adAuctionHeaders,align,allow,allowFullscreen,allowPaymentRequest,browsingTopics,contentDocument," + + "contentWindow,credentialless,csp,featurePolicy,frameBorder,getSVGDocument(),height,loading," + + "longDesc,marginHeight,marginWidth,name,privateToken,referrerPolicy,sandbox,scrolling," + "sharedStorageWritable,src,srcdoc," + "width", - EDGE = "adAuctionHeaders,align,allow,allowFullscreen,allowPaymentRequest,contentDocument,contentWindow," - + "credentialless,csp,featurePolicy,frameBorder,getSVGDocument(),height,loading,longDesc," - + "marginHeight,marginWidth,name,privateToken,referrerPolicy,sandbox,scrolling," + EDGE = "adAuctionHeaders,align,allow,allowFullscreen,allowPaymentRequest,browsingTopics,contentDocument," + + "contentWindow,credentialless,csp,featurePolicy,frameBorder,getSVGDocument(),height,loading," + + "longDesc,marginHeight,marginWidth,name,privateToken,referrerPolicy,sandbox,scrolling," + "sharedStorageWritable,src,srcdoc," + "width", FF = "align,allow,allowFullscreen,contentDocument,contentWindow,frameBorder,getSVGDocument(),height," @@ -3156,23 +3153,18 @@ public void var() throws Exception { * @throws Exception if the test fails */ @Test - @Alerts(CHROME = "addTextTrack(),autoplay,buffered,cancelVideoFrameCallback()," - + "canPlayType(),captureStream(),controls,controlsList,crossOrigin,currentSrc,currentTime," - + "defaultMuted,defaultPlaybackRate,disablePictureInPicture,disableRemotePlayback,duration," - + "ended,error,getVideoPlaybackQuality(),HAVE_CURRENT_DATA,HAVE_ENOUGH_DATA," - + "HAVE_FUTURE_DATA,HAVE_METADATA,HAVE_NOTHING,height,load(),loop,mediaKeys,muted,NETWORK_EMPTY," - + "NETWORK_IDLE,NETWORK_LOADING,NETWORK_NO_SOURCE,networkState,onencrypted," - + "onenterpictureinpicture,onleavepictureinpicture," - + "onwaitingforkey,pause(),paused,play(),playbackRate,played,playsInline," - + "poster,preload,preservesPitch," - + "readyState,remote,requestPictureInPicture(),requestVideoFrameCallback()," - + "seekable,seeking,setMediaKeys(),setSinkId(),sinkId,src,srcObject," - + "textTracks,videoHeight,videoWidth," - + "volume,webkitAudioDecodedByteCount,webkitDecodedFrameCount," - + "webkitDisplayingFullscreen,webkitDroppedFrameCount," - + "webkitEnterFullScreen(),webkitEnterFullscreen()," - + "webkitExitFullScreen(),webkitExitFullscreen()," - + "webkitSupportsFullscreen,webkitVideoDecodedByteCount,width", + @Alerts(CHROME = "addTextTrack(),autoplay,buffered,cancelVideoFrameCallback(),canPlayType(),captureStream()," + + "controls,controlsList,crossOrigin,currentSrc,currentTime,defaultMuted,defaultPlaybackRate," + + "disablePictureInPicture,disableRemotePlayback,duration,ended,error,getVideoPlaybackQuality()," + + "HAVE_CURRENT_DATA,HAVE_ENOUGH_DATA,HAVE_FUTURE_DATA,HAVE_METADATA,HAVE_NOTHING,height,load()," + + "loop,mediaKeys,muted,NETWORK_EMPTY,NETWORK_IDLE,NETWORK_LOADING,NETWORK_NO_SOURCE,networkState," + + "onencrypted,onenterpictureinpicture,onleavepictureinpicture,onwaitingforkey,pause(),paused," + + "play(),playbackRate,played,playsInline,poster,preload,preservesPitch,readyState,remote," + + "requestPictureInPicture(),requestVideoFrameCallback(),seekable,seeking,setMediaKeys()," + + "setSinkId(),sinkId,src,srcObject,textTracks,videoHeight,videoWidth,volume," + + "webkitAudioDecodedByteCount,webkitDecodedFrameCount,webkitDroppedFrameCount," + + "webkitVideoDecodedByteCount," + + "width", EDGE = "addTextTrack(),autoplay,buffered,cancelVideoFrameCallback(),canPlayType(),captureStream()," + "controls,controlsList,crossOrigin,currentSrc,currentTime,defaultMuted,defaultPlaybackRate," + "disablePictureInPicture,disableRemotePlayback,duration,ended,error,getVideoPlaybackQuality()," @@ -3183,9 +3175,7 @@ public void var() throws Exception { + "poster,preload,preservesPitch,readyState,remote,requestPictureInPicture()," + "requestVideoFrameCallback(),seekable,seeking,setMediaKeys(),setSinkId(),sinkId,src,srcObject," + "textTracks,videoHeight,videoWidth,volume,webkitAudioDecodedByteCount,webkitDecodedFrameCount," - + "webkitDisplayingFullscreen,webkitDroppedFrameCount,webkitEnterFullScreen()," - + "webkitEnterFullscreen(),webkitExitFullScreen(),webkitExitFullscreen(),webkitSupportsFullscreen," - + "webkitVideoDecodedByteCount," + + "webkitDroppedFrameCount,webkitVideoDecodedByteCount," + "width", FF = "addTextTrack(),autoplay,buffered,canPlayType(),controls,crossOrigin,currentSrc,currentTime," + "defaultMuted,defaultPlaybackRate,disablePictureInPicture,duration,ended,error,fastSeek()," @@ -4219,14 +4209,14 @@ public void slot() throws Exception { */ @Test @Alerts(CHROME = "activeElement,addEventListener(),adoptedStyleSheets,adoptNode(),alinkColor,all,anchors,append()," - + "appendChild(),applets,ATTRIBUTE_NODE,baseURI,bgColor,body,captureEvents(),caretRangeFromPoint()," - + "CDATA_SECTION_NODE,characterSet,charset,childElementCount,childNodes,children,clear()," - + "cloneNode(),close(),COMMENT_NODE,compareDocumentPosition(),compatMode,contains(),contentType," - + "cookie,createAttribute(),createAttributeNS(),createCDATASection(),createComment()," - + "createDocumentFragment(),createElement(),createElementNS(),createEvent(),createExpression()," - + "createNodeIterator(),createNSResolver(),createProcessingInstruction(),createRange()," - + "createTextNode(),createTreeWalker(),currentScript,defaultView,designMode,dir,dispatchEvent()," - + "doctype,DOCUMENT_FRAGMENT_NODE,DOCUMENT_NODE,DOCUMENT_POSITION_CONTAINED_BY," + + "appendChild(),applets,ATTRIBUTE_NODE,baseURI,bgColor,body,browsingTopics(),captureEvents()," + + "caretRangeFromPoint(),CDATA_SECTION_NODE,characterSet,charset,childElementCount,childNodes," + + "children,clear(),cloneNode(),close(),COMMENT_NODE,compareDocumentPosition(),compatMode," + + "contains(),contentType,cookie,createAttribute(),createAttributeNS(),createCDATASection()," + + "createComment(),createDocumentFragment(),createElement(),createElementNS(),createEvent()," + + "createExpression(),createNodeIterator(),createNSResolver(),createProcessingInstruction()," + + "createRange(),createTextNode(),createTreeWalker(),currentScript,defaultView,designMode,dir," + + "dispatchEvent(),doctype,DOCUMENT_FRAGMENT_NODE,DOCUMENT_NODE,DOCUMENT_POSITION_CONTAINED_BY," + "DOCUMENT_POSITION_CONTAINS,DOCUMENT_POSITION_DISCONNECTED,DOCUMENT_POSITION_FOLLOWING," + "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC,DOCUMENT_POSITION_PRECEDING,DOCUMENT_TYPE_NODE," + "documentElement,documentURI,domain,ELEMENT_NODE,elementFromPoint(),elementsFromPoint(),embeds," @@ -4268,14 +4258,14 @@ public void slot() throws Exception { + "webkitVisibilityState,write(),writeln(),xmlEncoding,xmlStandalone," + "xmlVersion", EDGE = "activeElement,addEventListener(),adoptedStyleSheets,adoptNode(),alinkColor,all,anchors,append()," - + "appendChild(),applets,ATTRIBUTE_NODE,baseURI,bgColor,body,captureEvents(),caretRangeFromPoint()," - + "CDATA_SECTION_NODE,characterSet,charset,childElementCount,childNodes,children,clear()," - + "cloneNode(),close(),COMMENT_NODE,compareDocumentPosition(),compatMode,contains(),contentType," - + "cookie,createAttribute(),createAttributeNS(),createCDATASection(),createComment()," - + "createDocumentFragment(),createElement(),createElementNS(),createEvent(),createExpression()," - + "createNodeIterator(),createNSResolver(),createProcessingInstruction(),createRange()," - + "createTextNode(),createTreeWalker(),currentScript,defaultView,designMode,dir,dispatchEvent()," - + "doctype,DOCUMENT_FRAGMENT_NODE,DOCUMENT_NODE,DOCUMENT_POSITION_CONTAINED_BY," + + "appendChild(),applets,ATTRIBUTE_NODE,baseURI,bgColor,body,browsingTopics(),captureEvents()," + + "caretRangeFromPoint(),CDATA_SECTION_NODE,characterSet,charset,childElementCount,childNodes," + + "children,clear(),cloneNode(),close(),COMMENT_NODE,compareDocumentPosition(),compatMode," + + "contains(),contentType,cookie,createAttribute(),createAttributeNS(),createCDATASection()," + + "createComment(),createDocumentFragment(),createElement(),createElementNS(),createEvent()," + + "createExpression(),createNodeIterator(),createNSResolver(),createProcessingInstruction()," + + "createRange(),createTextNode(),createTreeWalker(),currentScript,defaultView,designMode,dir," + + "dispatchEvent(),doctype,DOCUMENT_FRAGMENT_NODE,DOCUMENT_NODE,DOCUMENT_POSITION_CONTAINED_BY," + "DOCUMENT_POSITION_CONTAINS,DOCUMENT_POSITION_DISCONNECTED,DOCUMENT_POSITION_FOLLOWING," + "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC,DOCUMENT_POSITION_PRECEDING,DOCUMENT_TYPE_NODE," + "documentElement,documentURI,domain,ELEMENT_NODE,elementFromPoint(),elementsFromPoint(),embeds," @@ -4419,14 +4409,14 @@ public void document() throws Exception { */ @Test @Alerts(CHROME = "activeElement,addEventListener(),adoptedStyleSheets,adoptNode(),alinkColor,all,anchors,append()," - + "appendChild(),applets,ATTRIBUTE_NODE,baseURI,bgColor,body,captureEvents(),caretRangeFromPoint()," - + "CDATA_SECTION_NODE,characterSet,charset,childElementCount,childNodes,children,clear()," - + "cloneNode(),close(),COMMENT_NODE,compareDocumentPosition(),compatMode,contains(),contentType," - + "cookie,createAttribute(),createAttributeNS(),createCDATASection(),createComment()," - + "createDocumentFragment(),createElement(),createElementNS(),createEvent(),createExpression()," - + "createNodeIterator(),createNSResolver(),createProcessingInstruction(),createRange()," - + "createTextNode(),createTreeWalker(),currentScript,defaultView,designMode,dir,dispatchEvent()," - + "doctype,DOCUMENT_FRAGMENT_NODE,DOCUMENT_NODE,DOCUMENT_POSITION_CONTAINED_BY," + + "appendChild(),applets,ATTRIBUTE_NODE,baseURI,bgColor,body,browsingTopics(),captureEvents()," + + "caretRangeFromPoint(),CDATA_SECTION_NODE,characterSet,charset,childElementCount,childNodes," + + "children,clear(),cloneNode(),close(),COMMENT_NODE,compareDocumentPosition(),compatMode," + + "contains(),contentType,cookie,createAttribute(),createAttributeNS(),createCDATASection()," + + "createComment(),createDocumentFragment(),createElement(),createElementNS(),createEvent()," + + "createExpression(),createNodeIterator(),createNSResolver(),createProcessingInstruction()," + + "createRange(),createTextNode(),createTreeWalker(),currentScript,defaultView,designMode,dir," + + "dispatchEvent(),doctype,DOCUMENT_FRAGMENT_NODE,DOCUMENT_NODE,DOCUMENT_POSITION_CONTAINED_BY," + "DOCUMENT_POSITION_CONTAINS,DOCUMENT_POSITION_DISCONNECTED,DOCUMENT_POSITION_FOLLOWING," + "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC,DOCUMENT_POSITION_PRECEDING,DOCUMENT_TYPE_NODE," + "documentElement,documentURI,domain,ELEMENT_NODE,elementFromPoint(),elementsFromPoint(),embeds," @@ -4468,14 +4458,14 @@ public void document() throws Exception { + "webkitVisibilityState,write(),writeln(),xmlEncoding,xmlStandalone," + "xmlVersion", EDGE = "activeElement,addEventListener(),adoptedStyleSheets,adoptNode(),alinkColor,all,anchors,append()," - + "appendChild(),applets,ATTRIBUTE_NODE,baseURI,bgColor,body,captureEvents(),caretRangeFromPoint()," - + "CDATA_SECTION_NODE,characterSet,charset,childElementCount,childNodes,children,clear()," - + "cloneNode(),close(),COMMENT_NODE,compareDocumentPosition(),compatMode,contains(),contentType," - + "cookie,createAttribute(),createAttributeNS(),createCDATASection(),createComment()," - + "createDocumentFragment(),createElement(),createElementNS(),createEvent(),createExpression()," - + "createNodeIterator(),createNSResolver(),createProcessingInstruction(),createRange()," - + "createTextNode(),createTreeWalker(),currentScript,defaultView,designMode,dir,dispatchEvent()," - + "doctype,DOCUMENT_FRAGMENT_NODE,DOCUMENT_NODE,DOCUMENT_POSITION_CONTAINED_BY," + + "appendChild(),applets,ATTRIBUTE_NODE,baseURI,bgColor,body,browsingTopics(),captureEvents()," + + "caretRangeFromPoint(),CDATA_SECTION_NODE,characterSet,charset,childElementCount,childNodes," + + "children,clear(),cloneNode(),close(),COMMENT_NODE,compareDocumentPosition(),compatMode," + + "contains(),contentType,cookie,createAttribute(),createAttributeNS(),createCDATASection()," + + "createComment(),createDocumentFragment(),createElement(),createElementNS(),createEvent()," + + "createExpression(),createNodeIterator(),createNSResolver(),createProcessingInstruction()," + + "createRange(),createTextNode(),createTreeWalker(),currentScript,defaultView,designMode,dir," + + "dispatchEvent(),doctype,DOCUMENT_FRAGMENT_NODE,DOCUMENT_NODE,DOCUMENT_POSITION_CONTAINED_BY," + "DOCUMENT_POSITION_CONTAINS,DOCUMENT_POSITION_DISCONNECTED,DOCUMENT_POSITION_FOLLOWING," + "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC,DOCUMENT_POSITION_PRECEDING,DOCUMENT_TYPE_NODE," + "documentElement,documentURI,domain,ELEMENT_NODE,elementFromPoint(),elementsFromPoint(),embeds," @@ -4739,14 +4729,14 @@ public void htmlDocument() throws Exception { */ @Test @Alerts(CHROME = "activeElement,addEventListener(),adoptedStyleSheets,adoptNode(),alinkColor,all,anchors,append()," - + "appendChild(),applets,ATTRIBUTE_NODE,baseURI,bgColor,body,captureEvents(),caretRangeFromPoint()," - + "CDATA_SECTION_NODE,characterSet,charset,childElementCount,childNodes,children,clear()," - + "cloneNode(),close(),COMMENT_NODE,compareDocumentPosition(),compatMode,contains(),contentType," - + "cookie,createAttribute(),createAttributeNS(),createCDATASection(),createComment()," - + "createDocumentFragment(),createElement(),createElementNS(),createEvent(),createExpression()," - + "createNodeIterator(),createNSResolver(),createProcessingInstruction(),createRange()," - + "createTextNode(),createTreeWalker(),currentScript,defaultView,designMode,dir,dispatchEvent()," - + "doctype,DOCUMENT_FRAGMENT_NODE,DOCUMENT_NODE,DOCUMENT_POSITION_CONTAINED_BY," + + "appendChild(),applets,ATTRIBUTE_NODE,baseURI,bgColor,body,browsingTopics(),captureEvents()," + + "caretRangeFromPoint(),CDATA_SECTION_NODE,characterSet,charset,childElementCount,childNodes," + + "children,clear(),cloneNode(),close(),COMMENT_NODE,compareDocumentPosition(),compatMode," + + "contains(),contentType,cookie,createAttribute(),createAttributeNS(),createCDATASection()," + + "createComment(),createDocumentFragment(),createElement(),createElementNS(),createEvent()," + + "createExpression(),createNodeIterator(),createNSResolver(),createProcessingInstruction()," + + "createRange(),createTextNode(),createTreeWalker(),currentScript,defaultView,designMode,dir," + + "dispatchEvent(),doctype,DOCUMENT_FRAGMENT_NODE,DOCUMENT_NODE,DOCUMENT_POSITION_CONTAINED_BY," + "DOCUMENT_POSITION_CONTAINS,DOCUMENT_POSITION_DISCONNECTED,DOCUMENT_POSITION_FOLLOWING," + "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC,DOCUMENT_POSITION_PRECEDING,DOCUMENT_TYPE_NODE," + "documentElement,documentURI,domain,ELEMENT_NODE,elementFromPoint(),elementsFromPoint(),embeds," @@ -4788,14 +4778,14 @@ public void htmlDocument() throws Exception { + "webkitVisibilityState,write(),writeln(),xmlEncoding,xmlStandalone," + "xmlVersion", EDGE = "activeElement,addEventListener(),adoptedStyleSheets,adoptNode(),alinkColor,all,anchors,append()," - + "appendChild(),applets,ATTRIBUTE_NODE,baseURI,bgColor,body,captureEvents(),caretRangeFromPoint()," - + "CDATA_SECTION_NODE,characterSet,charset,childElementCount,childNodes,children,clear()," - + "cloneNode(),close(),COMMENT_NODE,compareDocumentPosition(),compatMode,contains(),contentType," - + "cookie,createAttribute(),createAttributeNS(),createCDATASection(),createComment()," - + "createDocumentFragment(),createElement(),createElementNS(),createEvent(),createExpression()," - + "createNodeIterator(),createNSResolver(),createProcessingInstruction(),createRange()," - + "createTextNode(),createTreeWalker(),currentScript,defaultView,designMode,dir,dispatchEvent()," - + "doctype,DOCUMENT_FRAGMENT_NODE,DOCUMENT_NODE,DOCUMENT_POSITION_CONTAINED_BY," + + "appendChild(),applets,ATTRIBUTE_NODE,baseURI,bgColor,body,browsingTopics(),captureEvents()," + + "caretRangeFromPoint(),CDATA_SECTION_NODE,characterSet,charset,childElementCount,childNodes," + + "children,clear(),cloneNode(),close(),COMMENT_NODE,compareDocumentPosition(),compatMode," + + "contains(),contentType,cookie,createAttribute(),createAttributeNS(),createCDATASection()," + + "createComment(),createDocumentFragment(),createElement(),createElementNS(),createEvent()," + + "createExpression(),createNodeIterator(),createNSResolver(),createProcessingInstruction()," + + "createRange(),createTextNode(),createTreeWalker(),currentScript,defaultView,designMode,dir," + + "dispatchEvent(),doctype,DOCUMENT_FRAGMENT_NODE,DOCUMENT_NODE,DOCUMENT_POSITION_CONTAINED_BY," + "DOCUMENT_POSITION_CONTAINS,DOCUMENT_POSITION_DISCONNECTED,DOCUMENT_POSITION_FOLLOWING," + "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC,DOCUMENT_POSITION_PRECEDING,DOCUMENT_TYPE_NODE," + "documentElement,documentURI,domain,ELEMENT_NODE,elementFromPoint(),elementsFromPoint(),embeds," @@ -5378,7 +5368,7 @@ public void range() throws Exception { + "nodeType,nodeValue,normalize(),NOTATION_NODE,ownerDocument,parentElement,parentNode,prepend()," + "previousSibling,PROCESSING_INSTRUCTION_NODE,querySelector(),querySelectorAll(),removeChild()," + "removeEventListener(),replaceChild(),replaceChildren(),TEXT_NODE,textContent") - @HtmlUnitNYI(CHROME = "addEventListener(),appendChild(),ATTRIBUTE_NODE,baseURI,CDATA_SECTION_NODE," + @HtmlUnitNYI(CHROME = "addEventListener(),append(),appendChild(),ATTRIBUTE_NODE,baseURI,CDATA_SECTION_NODE," + "childElementCount,childNodes," + "children,cloneNode(),COMMENT_NODE,compareDocumentPosition(),contains()," + "dispatchEvent(),DOCUMENT_FRAGMENT_NODE," @@ -5389,9 +5379,10 @@ public void range() throws Exception { + "firstChild,firstElementChild,getElementById(),getRootNode()," + "hasChildNodes(),insertBefore(),isEqualNode(),isSameNode(),lastChild," + "lastElementChild,nextSibling,nodeName,nodeType,nodeValue,normalize(),NOTATION_NODE,ownerDocument," - + "parentElement,parentNode,previousSibling,PROCESSING_INSTRUCTION_NODE,querySelector()," - + "querySelectorAll(),removeChild(),removeEventListener(),replaceChild(),TEXT_NODE,textContent", - EDGE = "addEventListener(),appendChild(),ATTRIBUTE_NODE,baseURI,CDATA_SECTION_NODE," + + "parentElement,parentNode,prepend(),previousSibling,PROCESSING_INSTRUCTION_NODE,querySelector()," + + "querySelectorAll(),removeChild(),removeEventListener(),replaceChild(),replaceChildren()," + + "TEXT_NODE,textContent", + EDGE = "addEventListener(),append(),appendChild(),ATTRIBUTE_NODE,baseURI,CDATA_SECTION_NODE," + "childElementCount,childNodes," + "children,cloneNode(),COMMENT_NODE,compareDocumentPosition(),contains()," + "dispatchEvent(),DOCUMENT_FRAGMENT_NODE," @@ -5402,9 +5393,10 @@ public void range() throws Exception { + "firstChild,firstElementChild,getElementById(),getRootNode()," + "hasChildNodes(),insertBefore(),isEqualNode(),isSameNode(),lastChild," + "lastElementChild,nextSibling,nodeName,nodeType,nodeValue,normalize(),NOTATION_NODE,ownerDocument," - + "parentElement,parentNode,previousSibling,PROCESSING_INSTRUCTION_NODE,querySelector()," - + "querySelectorAll(),removeChild(),removeEventListener(),replaceChild(),TEXT_NODE,textContent", - FF_ESR = "addEventListener(),appendChild(),ATTRIBUTE_NODE,baseURI,CDATA_SECTION_NODE," + + "parentElement,parentNode,prepend(),previousSibling,PROCESSING_INSTRUCTION_NODE,querySelector()," + + "querySelectorAll(),removeChild(),removeEventListener(),replaceChild(),replaceChildren()," + + "TEXT_NODE,textContent", + FF_ESR = "addEventListener(),append(),appendChild(),ATTRIBUTE_NODE,baseURI,CDATA_SECTION_NODE," + "childElementCount,childNodes," + "children,cloneNode(),COMMENT_NODE,compareDocumentPosition(),contains()," + "dispatchEvent(),DOCUMENT_FRAGMENT_NODE," @@ -5415,9 +5407,10 @@ public void range() throws Exception { + "firstChild,firstElementChild,getElementById(),getRootNode()," + "hasChildNodes(),insertBefore(),isEqualNode(),isSameNode(),lastChild," + "lastElementChild,nextSibling,nodeName,nodeType,nodeValue,normalize(),NOTATION_NODE,ownerDocument," - + "parentElement,parentNode,previousSibling,PROCESSING_INSTRUCTION_NODE,querySelector()," - + "querySelectorAll(),removeChild(),removeEventListener(),replaceChild(),TEXT_NODE,textContent", - FF = "addEventListener(),appendChild(),ATTRIBUTE_NODE,baseURI,CDATA_SECTION_NODE," + + "parentElement,parentNode,prepend(),previousSibling,PROCESSING_INSTRUCTION_NODE,querySelector()," + + "querySelectorAll(),removeChild(),removeEventListener(),replaceChild(),replaceChildren()," + + "TEXT_NODE,textContent", + FF = "addEventListener(),append(),appendChild(),ATTRIBUTE_NODE,baseURI,CDATA_SECTION_NODE," + "childElementCount,childNodes," + "children,cloneNode(),COMMENT_NODE,compareDocumentPosition(),contains()," + "dispatchEvent(),DOCUMENT_FRAGMENT_NODE," @@ -5428,8 +5421,9 @@ public void range() throws Exception { + "firstChild,firstElementChild,getElementById(),getRootNode()," + "hasChildNodes(),insertBefore(),isEqualNode(),isSameNode(),lastChild," + "lastElementChild,nextSibling,nodeName,nodeType,nodeValue,normalize(),NOTATION_NODE,ownerDocument," - + "parentElement,parentNode,previousSibling,PROCESSING_INSTRUCTION_NODE,querySelector()," - + "querySelectorAll(),removeChild(),removeEventListener(),replaceChild(),TEXT_NODE,textContent") + + "parentElement,parentNode,prepend(),previousSibling,PROCESSING_INSTRUCTION_NODE,querySelector()," + + "querySelectorAll(),removeChild(),removeEventListener(),replaceChild(),replaceChildren()," + + "TEXT_NODE,textContent") public void documentFragment() throws Exception { testString("", "document.createDocumentFragment()"); } @@ -6183,23 +6177,24 @@ public void nodeListButtonLabels() throws Exception { + "marginRight,marginTop,marker,markerEnd,markerMid,markerStart,mask,maskClip,maskComposite," + "maskImage,maskMode,maskOrigin,maskPosition,maskRepeat,maskSize,maskType,mathDepth,mathShift," + "mathStyle,maxBlockSize,maxHeight,maxInlineSize,maxWidth,minBlockSize,minHeight,minInlineSize," - + "minWidth,mixBlendMode,negative,objectFit,objectPosition,objectViewBox,offset,offsetAnchor," - + "offsetDistance,offsetPath,offsetPosition,offsetRotate,opacity,order,orphans,outline,outlineColor," - + "outlineOffset,outlineStyle,outlineWidth,overflow,overflowAnchor,overflowClipMargin,overflowWrap," - + "overflowX,overflowY,overlay,overrideColors,overscrollBehavior,overscrollBehaviorBlock," - + "overscrollBehaviorInline,overscrollBehaviorX,overscrollBehaviorY,pad,padding,paddingBlock," - + "paddingBlockEnd,paddingBlockStart,paddingBottom,paddingInline,paddingInlineEnd," - + "paddingInlineStart,paddingLeft,paddingRight,paddingTop,page,pageBreakAfter,pageBreakBefore," - + "pageBreakInside,pageOrientation,paintOrder,parentRule,perspective,perspectiveOrigin,placeContent," - + "placeItems,placeSelf,pointerEvents,position,positionAnchor,positionTry,positionTryOptions," - + "positionTryOrder,positionVisibility,prefix,quotes,r,range,removeProperty(),resize,right,rotate," - + "rowGap,rubyPosition,rx,ry,scale,scrollbarColor,scrollbarGutter,scrollbarWidth,scrollBehavior," - + "scrollMargin,scrollMarginBlock,scrollMarginBlockEnd,scrollMarginBlockStart,scrollMarginBottom," - + "scrollMarginInline,scrollMarginInlineEnd,scrollMarginInlineStart,scrollMarginLeft," - + "scrollMarginRight,scrollMarginTop,scrollPadding,scrollPaddingBlock,scrollPaddingBlockEnd," - + "scrollPaddingBlockStart,scrollPaddingBottom,scrollPaddingInline,scrollPaddingInlineEnd," - + "scrollPaddingInlineStart,scrollPaddingLeft,scrollPaddingRight,scrollPaddingTop,scrollSnapAlign," - + "scrollSnapStop,scrollSnapType,scrollTimeline,scrollTimelineAxis,scrollTimelineName,setProperty()," + + "minWidth,mixBlendMode,navigation,negative,objectFit,objectPosition,objectViewBox,offset," + + "offsetAnchor,offsetDistance,offsetPath,offsetPosition,offsetRotate,opacity,order,orphans,outline," + + "outlineColor,outlineOffset,outlineStyle,outlineWidth,overflow,overflowAnchor,overflowClipMargin," + + "overflowWrap,overflowX,overflowY,overlay,overrideColors,overscrollBehavior," + + "overscrollBehaviorBlock,overscrollBehaviorInline,overscrollBehaviorX,overscrollBehaviorY,pad," + + "padding,paddingBlock,paddingBlockEnd,paddingBlockStart,paddingBottom,paddingInline," + + "paddingInlineEnd,paddingInlineStart,paddingLeft,paddingRight,paddingTop,page,pageBreakAfter," + + "pageBreakBefore,pageBreakInside,pageOrientation,paintOrder,parentRule,perspective," + + "perspectiveOrigin,placeContent,placeItems,placeSelf,pointerEvents,position,positionAnchor," + + "positionTry,positionTryOptions,positionTryOrder,positionVisibility,prefix,quotes,r,range," + + "removeProperty(),resize,right,rotate,rowGap,rubyPosition,rx,ry,scale,scrollbarColor," + + "scrollbarGutter,scrollbarWidth,scrollBehavior,scrollMargin,scrollMarginBlock," + + "scrollMarginBlockEnd,scrollMarginBlockStart,scrollMarginBottom,scrollMarginInline," + + "scrollMarginInlineEnd,scrollMarginInlineStart,scrollMarginLeft,scrollMarginRight,scrollMarginTop," + + "scrollPadding,scrollPaddingBlock,scrollPaddingBlockEnd,scrollPaddingBlockStart," + + "scrollPaddingBottom,scrollPaddingInline,scrollPaddingInlineEnd,scrollPaddingInlineStart," + + "scrollPaddingLeft,scrollPaddingRight,scrollPaddingTop,scrollSnapAlign,scrollSnapStop," + + "scrollSnapType,scrollTimeline,scrollTimelineAxis,scrollTimelineName,setProperty()," + "shapeImageThreshold,shapeMargin,shapeOutside,shapeRendering,size,sizeAdjust,speak,speakAs,src," + "stopColor,stopOpacity,stroke,strokeDasharray,strokeDashoffset,strokeLinecap,strokeLinejoin," + "strokeMiterlimit,strokeOpacity,strokeWidth,suffix,symbols,syntax,system,tableLayout,tabSize," @@ -6209,7 +6204,7 @@ public void nodeListButtonLabels() throws Exception { + "textOverflow,textRendering,textShadow,textSizeAdjust,textSpacingTrim,textTransform," + "textUnderlineOffset,textUnderlinePosition,textWrap,timelineScope,top,touchAction,transform," + "transformBox,transformOrigin,transformStyle,transition,transitionBehavior,transitionDelay," - + "transitionDuration,transitionProperty,transitionTimingFunction,translate,unicodeBidi," + + "transitionDuration,transitionProperty,transitionTimingFunction,translate,types,unicodeBidi," + "unicodeRange,userSelect,vectorEffect,verticalAlign,viewTimeline,viewTimelineAxis," + "viewTimelineInset,viewTimelineName,viewTransitionClass,viewTransitionName,visibility," + "webkitAlignContent,webkitAlignItems,webkitAlignSelf,webkitAnimation,webkitAnimationDelay," @@ -6311,23 +6306,24 @@ public void nodeListButtonLabels() throws Exception { + "marginRight,marginTop,marker,markerEnd,markerMid,markerStart,mask,maskClip,maskComposite," + "maskImage,maskMode,maskOrigin,maskPosition,maskRepeat,maskSize,maskType,mathDepth,mathShift," + "mathStyle,maxBlockSize,maxHeight,maxInlineSize,maxWidth,minBlockSize,minHeight,minInlineSize," - + "minWidth,mixBlendMode,negative,objectFit,objectPosition,objectViewBox,offset,offsetAnchor," - + "offsetDistance,offsetPath,offsetPosition,offsetRotate,opacity,order,orphans,outline,outlineColor," - + "outlineOffset,outlineStyle,outlineWidth,overflow,overflowAnchor,overflowClipMargin,overflowWrap," - + "overflowX,overflowY,overlay,overrideColors,overscrollBehavior,overscrollBehaviorBlock," - + "overscrollBehaviorInline,overscrollBehaviorX,overscrollBehaviorY,pad,padding,paddingBlock," - + "paddingBlockEnd,paddingBlockStart,paddingBottom,paddingInline,paddingInlineEnd," - + "paddingInlineStart,paddingLeft,paddingRight,paddingTop,page,pageBreakAfter,pageBreakBefore," - + "pageBreakInside,pageOrientation,paintOrder,parentRule,perspective,perspectiveOrigin,placeContent," - + "placeItems,placeSelf,pointerEvents,position,positionAnchor,positionTry,positionTryOptions," - + "positionTryOrder,positionVisibility,prefix,quotes,r,range,removeProperty(),resize,right,rotate," - + "rowGap,rubyPosition,rx,ry,scale,scrollbarColor,scrollbarGutter,scrollbarWidth,scrollBehavior," - + "scrollMargin,scrollMarginBlock,scrollMarginBlockEnd,scrollMarginBlockStart,scrollMarginBottom," - + "scrollMarginInline,scrollMarginInlineEnd,scrollMarginInlineStart,scrollMarginLeft," - + "scrollMarginRight,scrollMarginTop,scrollPadding,scrollPaddingBlock,scrollPaddingBlockEnd," - + "scrollPaddingBlockStart,scrollPaddingBottom,scrollPaddingInline,scrollPaddingInlineEnd," - + "scrollPaddingInlineStart,scrollPaddingLeft,scrollPaddingRight,scrollPaddingTop,scrollSnapAlign," - + "scrollSnapStop,scrollSnapType,scrollTimeline,scrollTimelineAxis,scrollTimelineName,setProperty()," + + "minWidth,mixBlendMode,navigation,negative,objectFit,objectPosition,objectViewBox,offset," + + "offsetAnchor,offsetDistance,offsetPath,offsetPosition,offsetRotate,opacity,order,orphans,outline," + + "outlineColor,outlineOffset,outlineStyle,outlineWidth,overflow,overflowAnchor,overflowClipMargin," + + "overflowWrap,overflowX,overflowY,overlay,overrideColors,overscrollBehavior," + + "overscrollBehaviorBlock,overscrollBehaviorInline,overscrollBehaviorX,overscrollBehaviorY,pad," + + "padding,paddingBlock,paddingBlockEnd,paddingBlockStart,paddingBottom,paddingInline," + + "paddingInlineEnd,paddingInlineStart,paddingLeft,paddingRight,paddingTop,page,pageBreakAfter," + + "pageBreakBefore,pageBreakInside,pageOrientation,paintOrder,parentRule,perspective," + + "perspectiveOrigin,placeContent,placeItems,placeSelf,pointerEvents,position,positionAnchor," + + "positionTry,positionTryOptions,positionTryOrder,positionVisibility,prefix,quotes,r,range," + + "removeProperty(),resize,right,rotate,rowGap,rubyPosition,rx,ry,scale,scrollbarColor," + + "scrollbarGutter,scrollbarWidth,scrollBehavior,scrollMargin,scrollMarginBlock," + + "scrollMarginBlockEnd,scrollMarginBlockStart,scrollMarginBottom,scrollMarginInline," + + "scrollMarginInlineEnd,scrollMarginInlineStart,scrollMarginLeft,scrollMarginRight,scrollMarginTop," + + "scrollPadding,scrollPaddingBlock,scrollPaddingBlockEnd,scrollPaddingBlockStart," + + "scrollPaddingBottom,scrollPaddingInline,scrollPaddingInlineEnd,scrollPaddingInlineStart," + + "scrollPaddingLeft,scrollPaddingRight,scrollPaddingTop,scrollSnapAlign,scrollSnapStop," + + "scrollSnapType,scrollTimeline,scrollTimelineAxis,scrollTimelineName,setProperty()," + "shapeImageThreshold,shapeMargin,shapeOutside,shapeRendering,size,sizeAdjust,speak,speakAs,src," + "stopColor,stopOpacity,stroke,strokeDasharray,strokeDashoffset,strokeLinecap,strokeLinejoin," + "strokeMiterlimit,strokeOpacity,strokeWidth,suffix,symbols,syntax,system,tableLayout,tabSize," @@ -6337,7 +6333,7 @@ public void nodeListButtonLabels() throws Exception { + "textOverflow,textRendering,textShadow,textSizeAdjust,textSpacingTrim,textTransform," + "textUnderlineOffset,textUnderlinePosition,textWrap,timelineScope,top,touchAction,transform," + "transformBox,transformOrigin,transformStyle,transition,transitionBehavior,transitionDelay," - + "transitionDuration,transitionProperty,transitionTimingFunction,translate,unicodeBidi," + + "transitionDuration,transitionProperty,transitionTimingFunction,translate,types,unicodeBidi," + "unicodeRange,userSelect,vectorEffect,verticalAlign,viewTimeline,viewTimelineAxis," + "viewTimelineInset,viewTimelineName,viewTransitionClass,viewTransitionName,visibility," + "webkitAlignContent,webkitAlignItems,webkitAlignSelf,webkitAnimation,webkitAnimationDelay," @@ -6882,7 +6878,8 @@ public void nodeListButtonLabels() throws Exception { + "maskClip,maskComposite,maskImage,maskMode,maskOrigin,maskPosition,maskRepeat,maskSize," + "maskType,mathDepth,mathShift,mathStyle," + "maxBlockSize,maxHeight,maxInlineSize,maxWidth,minBlockSize,minHeight," - + "minInlineSize,minWidth,mixBlendMode,negative,objectFit,objectPosition,objectViewBox,offset," + + "minInlineSize,minWidth,mixBlendMode,navigation,negative," + + "objectFit,objectPosition,objectViewBox,offset," + "offsetAnchor,offsetDistance,offsetPath,offsetPosition," + "offsetRotate,opacity,order,orphans,outline,outlineColor," + "outlineOffset,outlineStyle,outlineWidth,overflow,overflowAnchor,overflowClipMargin,overflowWrap," @@ -6912,7 +6909,7 @@ public void nodeListButtonLabels() throws Exception { + "textTransform,textUnderlineOffset,textUnderlinePosition,textWrap,timelineScope," + "top,touchAction,transform,transformBox,transformOrigin," + "transformStyle,transition,transitionBehavior,transitionDelay,transitionDuration,transitionProperty," - + "transitionTimingFunction,translate," + + "transitionTimingFunction,translate,types," + "unicodeBidi,unicodeRange,userSelect,vectorEffect,verticalAlign," + "viewTimeline,viewTimelineAxis,viewTimelineInset,viewTimelineName," + "viewTransitionClass,viewTransitionName," @@ -7009,7 +7006,8 @@ public void nodeListButtonLabels() throws Exception { + "maskClip,maskComposite,maskImage,maskMode,maskOrigin,maskPosition,maskRepeat,maskSize," + "maskType,mathDepth,mathShift,mathStyle," + "maxBlockSize,maxHeight,maxInlineSize,maxWidth,minBlockSize,minHeight," - + "minInlineSize,minWidth,mixBlendMode,negative,objectFit,objectPosition,objectViewBox,offset," + + "minInlineSize,minWidth,mixBlendMode,navigation,negative," + + "objectFit,objectPosition,objectViewBox,offset," + "offsetAnchor,offsetDistance,offsetPath,offsetPosition," + "offsetRotate,opacity,order,orphans,outline,outlineColor," + "outlineOffset,outlineStyle,outlineWidth,overflow,overflowAnchor,overflowClipMargin,overflowWrap," @@ -7039,7 +7037,7 @@ public void nodeListButtonLabels() throws Exception { + "textTransform,textUnderlineOffset,textUnderlinePosition,textWrap,timelineScope," + "top,touchAction,transform,transformBox,transformOrigin," + "transformStyle,transition,transitionBehavior,transitionDelay,transitionDuration,transitionProperty," - + "transitionTimingFunction,translate," + + "transitionTimingFunction,translate,types," + "unicodeBidi,unicodeRange,userSelect,vectorEffect,verticalAlign," + "viewTimeline,viewTimelineAxis,viewTimelineInset,viewTimelineName," + "viewTransitionClass,viewTransitionName," @@ -7594,23 +7592,24 @@ public void computedStyle() throws Exception { + "marginRight,marginTop,marker,markerEnd,markerMid,markerStart,mask,maskClip,maskComposite," + "maskImage,maskMode,maskOrigin,maskPosition,maskRepeat,maskSize,maskType,mathDepth,mathShift," + "mathStyle,maxBlockSize,maxHeight,maxInlineSize,maxWidth,minBlockSize,minHeight,minInlineSize," - + "minWidth,mixBlendMode,negative,objectFit,objectPosition,objectViewBox,offset,offsetAnchor," - + "offsetDistance,offsetPath,offsetPosition,offsetRotate,opacity,order,orphans,outline,outlineColor," - + "outlineOffset,outlineStyle,outlineWidth,overflow,overflowAnchor,overflowClipMargin,overflowWrap," - + "overflowX,overflowY,overlay,overrideColors,overscrollBehavior,overscrollBehaviorBlock," - + "overscrollBehaviorInline,overscrollBehaviorX,overscrollBehaviorY,pad,padding,paddingBlock," - + "paddingBlockEnd,paddingBlockStart,paddingBottom,paddingInline,paddingInlineEnd," - + "paddingInlineStart,paddingLeft,paddingRight,paddingTop,page,pageBreakAfter,pageBreakBefore," - + "pageBreakInside,pageOrientation,paintOrder,parentRule,perspective,perspectiveOrigin,placeContent," - + "placeItems,placeSelf,pointerEvents,position,positionAnchor,positionTry,positionTryOptions," - + "positionTryOrder,positionVisibility,prefix,quotes,r,range,removeProperty(),resize,right,rotate," - + "rowGap,rubyPosition,rx,ry,scale,scrollbarColor,scrollbarGutter,scrollbarWidth,scrollBehavior," - + "scrollMargin,scrollMarginBlock,scrollMarginBlockEnd,scrollMarginBlockStart,scrollMarginBottom," - + "scrollMarginInline,scrollMarginInlineEnd,scrollMarginInlineStart,scrollMarginLeft," - + "scrollMarginRight,scrollMarginTop,scrollPadding,scrollPaddingBlock,scrollPaddingBlockEnd," - + "scrollPaddingBlockStart,scrollPaddingBottom,scrollPaddingInline,scrollPaddingInlineEnd," - + "scrollPaddingInlineStart,scrollPaddingLeft,scrollPaddingRight,scrollPaddingTop,scrollSnapAlign," - + "scrollSnapStop,scrollSnapType,scrollTimeline,scrollTimelineAxis,scrollTimelineName,setProperty()," + + "minWidth,mixBlendMode,navigation,negative,objectFit,objectPosition,objectViewBox,offset," + + "offsetAnchor,offsetDistance,offsetPath,offsetPosition,offsetRotate,opacity,order,orphans,outline," + + "outlineColor,outlineOffset,outlineStyle,outlineWidth,overflow,overflowAnchor,overflowClipMargin," + + "overflowWrap,overflowX,overflowY,overlay,overrideColors,overscrollBehavior," + + "overscrollBehaviorBlock,overscrollBehaviorInline,overscrollBehaviorX,overscrollBehaviorY,pad," + + "padding,paddingBlock,paddingBlockEnd,paddingBlockStart,paddingBottom,paddingInline," + + "paddingInlineEnd,paddingInlineStart,paddingLeft,paddingRight,paddingTop,page,pageBreakAfter," + + "pageBreakBefore,pageBreakInside,pageOrientation,paintOrder,parentRule,perspective," + + "perspectiveOrigin,placeContent,placeItems,placeSelf,pointerEvents,position,positionAnchor," + + "positionTry,positionTryOptions,positionTryOrder,positionVisibility,prefix,quotes,r,range," + + "removeProperty(),resize,right,rotate,rowGap,rubyPosition,rx,ry,scale,scrollbarColor," + + "scrollbarGutter,scrollbarWidth,scrollBehavior,scrollMargin,scrollMarginBlock," + + "scrollMarginBlockEnd,scrollMarginBlockStart,scrollMarginBottom,scrollMarginInline," + + "scrollMarginInlineEnd,scrollMarginInlineStart,scrollMarginLeft,scrollMarginRight,scrollMarginTop," + + "scrollPadding,scrollPaddingBlock,scrollPaddingBlockEnd,scrollPaddingBlockStart," + + "scrollPaddingBottom,scrollPaddingInline,scrollPaddingInlineEnd,scrollPaddingInlineStart," + + "scrollPaddingLeft,scrollPaddingRight,scrollPaddingTop,scrollSnapAlign,scrollSnapStop," + + "scrollSnapType,scrollTimeline,scrollTimelineAxis,scrollTimelineName,setProperty()," + "shapeImageThreshold,shapeMargin,shapeOutside,shapeRendering,size,sizeAdjust,speak,speakAs,src," + "stopColor,stopOpacity,stroke,strokeDasharray,strokeDashoffset,strokeLinecap,strokeLinejoin," + "strokeMiterlimit,strokeOpacity,strokeWidth,suffix,symbols,syntax,system,tableLayout,tabSize," @@ -7620,7 +7619,7 @@ public void computedStyle() throws Exception { + "textOverflow,textRendering,textShadow,textSizeAdjust,textSpacingTrim,textTransform," + "textUnderlineOffset,textUnderlinePosition,textWrap,timelineScope,top,touchAction,transform," + "transformBox,transformOrigin,transformStyle,transition,transitionBehavior,transitionDelay," - + "transitionDuration,transitionProperty,transitionTimingFunction,translate,unicodeBidi," + + "transitionDuration,transitionProperty,transitionTimingFunction,translate,types,unicodeBidi," + "unicodeRange,userSelect,vectorEffect,verticalAlign,viewTimeline,viewTimelineAxis," + "viewTimelineInset,viewTimelineName,viewTransitionClass,viewTransitionName,visibility," + "webkitAlignContent,webkitAlignItems,webkitAlignSelf,webkitAnimation,webkitAnimationDelay," @@ -7707,23 +7706,24 @@ public void computedStyle() throws Exception { + "marginRight,marginTop,marker,markerEnd,markerMid,markerStart,mask,maskClip,maskComposite," + "maskImage,maskMode,maskOrigin,maskPosition,maskRepeat,maskSize,maskType,mathDepth,mathShift," + "mathStyle,maxBlockSize,maxHeight,maxInlineSize,maxWidth,minBlockSize,minHeight,minInlineSize," - + "minWidth,mixBlendMode,negative,objectFit,objectPosition,objectViewBox,offset,offsetAnchor," - + "offsetDistance,offsetPath,offsetPosition,offsetRotate,opacity,order,orphans,outline,outlineColor," - + "outlineOffset,outlineStyle,outlineWidth,overflow,overflowAnchor,overflowClipMargin,overflowWrap," - + "overflowX,overflowY,overlay,overrideColors,overscrollBehavior,overscrollBehaviorBlock," - + "overscrollBehaviorInline,overscrollBehaviorX,overscrollBehaviorY,pad,padding,paddingBlock," - + "paddingBlockEnd,paddingBlockStart,paddingBottom,paddingInline,paddingInlineEnd," - + "paddingInlineStart,paddingLeft,paddingRight,paddingTop,page,pageBreakAfter,pageBreakBefore," - + "pageBreakInside,pageOrientation,paintOrder,parentRule,perspective,perspectiveOrigin,placeContent," - + "placeItems,placeSelf,pointerEvents,position,positionAnchor,positionTry,positionTryOptions," - + "positionTryOrder,positionVisibility,prefix,quotes,r,range,removeProperty(),resize,right,rotate," - + "rowGap,rubyPosition,rx,ry,scale,scrollbarColor,scrollbarGutter,scrollbarWidth,scrollBehavior," - + "scrollMargin,scrollMarginBlock,scrollMarginBlockEnd,scrollMarginBlockStart,scrollMarginBottom," - + "scrollMarginInline,scrollMarginInlineEnd,scrollMarginInlineStart,scrollMarginLeft," - + "scrollMarginRight,scrollMarginTop,scrollPadding,scrollPaddingBlock,scrollPaddingBlockEnd," - + "scrollPaddingBlockStart,scrollPaddingBottom,scrollPaddingInline,scrollPaddingInlineEnd," - + "scrollPaddingInlineStart,scrollPaddingLeft,scrollPaddingRight,scrollPaddingTop,scrollSnapAlign," - + "scrollSnapStop,scrollSnapType,scrollTimeline,scrollTimelineAxis,scrollTimelineName,setProperty()," + + "minWidth,mixBlendMode,navigation,negative,objectFit,objectPosition,objectViewBox,offset," + + "offsetAnchor,offsetDistance,offsetPath,offsetPosition,offsetRotate,opacity,order,orphans,outline," + + "outlineColor,outlineOffset,outlineStyle,outlineWidth,overflow,overflowAnchor,overflowClipMargin," + + "overflowWrap,overflowX,overflowY,overlay,overrideColors,overscrollBehavior," + + "overscrollBehaviorBlock,overscrollBehaviorInline,overscrollBehaviorX,overscrollBehaviorY,pad," + + "padding,paddingBlock,paddingBlockEnd,paddingBlockStart,paddingBottom,paddingInline," + + "paddingInlineEnd,paddingInlineStart,paddingLeft,paddingRight,paddingTop,page,pageBreakAfter," + + "pageBreakBefore,pageBreakInside,pageOrientation,paintOrder,parentRule,perspective," + + "perspectiveOrigin,placeContent,placeItems,placeSelf,pointerEvents,position,positionAnchor," + + "positionTry,positionTryOptions,positionTryOrder,positionVisibility,prefix,quotes,r,range," + + "removeProperty(),resize,right,rotate,rowGap,rubyPosition,rx,ry,scale,scrollbarColor," + + "scrollbarGutter,scrollbarWidth,scrollBehavior,scrollMargin,scrollMarginBlock," + + "scrollMarginBlockEnd,scrollMarginBlockStart,scrollMarginBottom,scrollMarginInline," + + "scrollMarginInlineEnd,scrollMarginInlineStart,scrollMarginLeft,scrollMarginRight,scrollMarginTop," + + "scrollPadding,scrollPaddingBlock,scrollPaddingBlockEnd,scrollPaddingBlockStart," + + "scrollPaddingBottom,scrollPaddingInline,scrollPaddingInlineEnd,scrollPaddingInlineStart," + + "scrollPaddingLeft,scrollPaddingRight,scrollPaddingTop,scrollSnapAlign,scrollSnapStop," + + "scrollSnapType,scrollTimeline,scrollTimelineAxis,scrollTimelineName,setProperty()," + "shapeImageThreshold,shapeMargin,shapeOutside,shapeRendering,size,sizeAdjust,speak,speakAs,src," + "stopColor,stopOpacity,stroke,strokeDasharray,strokeDashoffset,strokeLinecap,strokeLinejoin," + "strokeMiterlimit,strokeOpacity,strokeWidth,suffix,symbols,syntax,system,tableLayout,tabSize," @@ -7733,7 +7733,7 @@ public void computedStyle() throws Exception { + "textOverflow,textRendering,textShadow,textSizeAdjust,textSpacingTrim,textTransform," + "textUnderlineOffset,textUnderlinePosition,textWrap,timelineScope,top,touchAction,transform," + "transformBox,transformOrigin,transformStyle,transition,transitionBehavior,transitionDelay," - + "transitionDuration,transitionProperty,transitionTimingFunction,translate,unicodeBidi," + + "transitionDuration,transitionProperty,transitionTimingFunction,translate,types,unicodeBidi," + "unicodeRange,userSelect,vectorEffect,verticalAlign,viewTimeline,viewTimelineAxis," + "viewTimelineInset,viewTimelineName,viewTransitionClass,viewTransitionName,visibility," + "webkitAlignContent,webkitAlignItems,webkitAlignSelf,webkitAnimation,webkitAnimationDelay," @@ -8317,6 +8317,34 @@ public void xPathResult() throws Exception { testString("var res = document.evaluate('/html/body', document, null, XPathResult.ANY_TYPE, null);", "res"); } + /** + * Test {@link XPathEvaluator}. + * + * @throws Exception if the test fails + */ + @Test + @Alerts(CHROME = "createExpression(),createNSResolver(),evaluate()", + EDGE = "createExpression(),createNSResolver(),evaluate()", + FF = "createExpression(),createNSResolver(),evaluate()", + FF_ESR = "createExpression(),createNSResolver(),evaluate()") + public void xPathEvaluator() throws Exception { + testString("", "new XPathEvaluator()"); + } + + /** + * Test {@link XPathExpression}. + * + * @throws Exception if the test fails + */ + @Test + @Alerts(CHROME = "evaluate()", + EDGE = "evaluate()", + FF = "evaluate()", + FF_ESR = "evaluate()") + public void xPathExpression() throws Exception { + testString("var res = new XPathEvaluator().createExpression('//span')", "res"); + } + /** * Test {@link CDATASection}. * @@ -8633,14 +8661,31 @@ public void cssStyleSheet() throws Exception { * @throws Exception if the test fails */ @Test - @Alerts(DEFAULT = "CHARSET_RULE,COUNTER_STYLE_RULE,cssText,FONT_FACE_RULE,FONT_FEATURE_VALUES_RULE," - + "IMPORT_RULE,KEYFRAME_RULE,KEYFRAMES_RULE,MEDIA_RULE,NAMESPACE_RULE,PAGE_RULE,parentRule," - + "parentStyleSheet,selectorText,style,STYLE_RULE,SUPPORTS_RULE,type", + @Alerts(CHROME = "CHARSET_RULE,COUNTER_STYLE_RULE,cssRules,cssText,deleteRule(),FONT_FACE_RULE," + + "FONT_FEATURE_VALUES_RULE,IMPORT_RULE,insertRule(),KEYFRAME_RULE,KEYFRAMES_RULE,MEDIA_RULE," + + "NAMESPACE_RULE,PAGE_RULE,parentRule,parentStyleSheet,selectorText,style,STYLE_RULE,SUPPORTS_RULE," + + "type", + EDGE = "CHARSET_RULE,COUNTER_STYLE_RULE,cssRules,cssText,deleteRule(),FONT_FACE_RULE," + + "FONT_FEATURE_VALUES_RULE,IMPORT_RULE,insertRule(),KEYFRAME_RULE,KEYFRAMES_RULE,MEDIA_RULE," + + "NAMESPACE_RULE,PAGE_RULE,parentRule,parentStyleSheet,selectorText,style,STYLE_RULE,SUPPORTS_RULE," + + "type", FF = "CHARSET_RULE,COUNTER_STYLE_RULE,cssRules,cssText,deleteRule(),FONT_FACE_RULE," + "FONT_FEATURE_VALUES_RULE,IMPORT_RULE,insertRule(),KEYFRAME_RULE,KEYFRAMES_RULE,MEDIA_RULE," + "NAMESPACE_RULE,PAGE_RULE,parentRule,parentStyleSheet,selectorText,style,STYLE_RULE,SUPPORTS_RULE," + + "type", + FF_ESR = "CHARSET_RULE,COUNTER_STYLE_RULE,cssText,FONT_FACE_RULE," + + "FONT_FEATURE_VALUES_RULE,IMPORT_RULE,KEYFRAME_RULE,KEYFRAMES_RULE,MEDIA_RULE," + + "NAMESPACE_RULE,PAGE_RULE,parentRule,parentStyleSheet,selectorText,style,STYLE_RULE,SUPPORTS_RULE," + "type") @HtmlUnitNYI( + CHROME = "CHARSET_RULE,COUNTER_STYLE_RULE,cssText,FONT_FACE_RULE," + + "FONT_FEATURE_VALUES_RULE,IMPORT_RULE,KEYFRAME_RULE,KEYFRAMES_RULE,MEDIA_RULE," + + "NAMESPACE_RULE,PAGE_RULE,parentRule,parentStyleSheet,selectorText,style,STYLE_RULE,SUPPORTS_RULE," + + "type", + EDGE = "CHARSET_RULE,COUNTER_STYLE_RULE,cssText,FONT_FACE_RULE," + + "FONT_FEATURE_VALUES_RULE,IMPORT_RULE,KEYFRAME_RULE,KEYFRAMES_RULE,MEDIA_RULE," + + "NAMESPACE_RULE,PAGE_RULE,parentRule,parentStyleSheet,selectorText,style,STYLE_RULE,SUPPORTS_RULE," + + "type", FF = "CHARSET_RULE,COUNTER_STYLE_RULE,cssText,FONT_FACE_RULE," + "FONT_FEATURE_VALUES_RULE,IMPORT_RULE,KEYFRAME_RULE,KEYFRAMES_RULE,MEDIA_RULE," + "NAMESPACE_RULE,PAGE_RULE,parentRule,parentStyleSheet,selectorText,style,STYLE_RULE,SUPPORTS_RULE," diff --git a/src/test/java/org/htmlunit/html/HtmlElementTest.java b/src/test/java/org/htmlunit/html/HtmlElementTest.java index 5b5bffd4c54..4b0ab27cac8 100644 --- a/src/test/java/org/htmlunit/html/HtmlElementTest.java +++ b/src/test/java/org/htmlunit/html/HtmlElementTest.java @@ -1219,13 +1219,35 @@ public void isDisplayedJsEngineDisabled() throws Exception { + ""; try (WebClient webClient = new WebClient(getBrowserVersion(), false, null, -1)) { - final HtmlPage page = loadPage(html); + final HtmlPage page = loadPage(webClient, html, null); + + assertFalse(page.getWebClient().isJavaScriptEngineEnabled()); assertEquals(Boolean.parseBoolean(getExpectedAlerts()[0]), page.getElementById("d1").isDisplayed()); assertEquals(Boolean.parseBoolean(getExpectedAlerts()[1]), page.getElementById("d2").isDisplayed()); assertEquals(Boolean.parseBoolean(getExpectedAlerts()[2]), page.getElementById("d3").isDisplayed()); } } + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"true", "false", "false"}) + public void clickJsEngineDisabled() throws Exception { + final String html = "\n" + + "\n" + + "\n" + + "
    hello
    \n" + + ""; + + try (WebClient webClient = new WebClient(getBrowserVersion(), false, null, -1)) { + final HtmlPage page = loadPage(webClient, html, null); + + assertFalse(page.getWebClient().isJavaScriptEngineEnabled()); + assertEquals(page, page.getElementById("d1").click()); + } + } + @Test public void acceptChar() throws Exception { final String html = ""; diff --git a/src/test/java/org/htmlunit/html/HtmlInputTest.java b/src/test/java/org/htmlunit/html/HtmlInputTest.java index 4db850c4fd1..cb6575e1fae 100644 --- a/src/test/java/org/htmlunit/html/HtmlInputTest.java +++ b/src/test/java/org/htmlunit/html/HtmlInputTest.java @@ -252,6 +252,8 @@ public void changeType_javascriptEngineDisabled() throws Exception { try (WebClient webClient = new WebClient(getBrowserVersion(), false, null, -1)) { final HtmlPage page = loadPage(webClient, htmlContent, null, URL_FIRST); + assertFalse(page.getWebClient().isJavaScriptEngineEnabled()); + final HtmlForm form = page.getHtmlElementById("form1"); final HtmlTextInput input = form.getInputByName("text1"); diff --git a/src/test/java/org/htmlunit/javascript/HtmlUnitScriptable2Test.java b/src/test/java/org/htmlunit/javascript/HtmlUnitScriptable2Test.java index 58cdf4cb6be..499145f38ec 100644 --- a/src/test/java/org/htmlunit/javascript/HtmlUnitScriptable2Test.java +++ b/src/test/java/org/htmlunit/javascript/HtmlUnitScriptable2Test.java @@ -14,10 +14,6 @@ */ package org.htmlunit.javascript; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Locale; - import org.htmlunit.WebDriverTestCase; import org.htmlunit.html.HtmlPageTest; import org.htmlunit.junit.BrowserRunner; @@ -209,46 +205,6 @@ public void passFunctionAsParameter() throws Exception { loadPageVerifyTitle2(html); } - /** - * Test JavaScript: 'new Date().getTimezoneOffset()' compared to java.text.SimpleDateFormat.format(). - * - * @throws Exception if the test fails - */ - @Test - public void dateGetTimezoneOffset() throws Exception { - final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ - + "\n" - + "\n" - + "\n" - + ""; - final String timeZone = new SimpleDateFormat("Z", Locale.ROOT) - .format(Calendar.getInstance(Locale.ROOT).getTime()); - final String hour = timeZone.substring(1, 3); - String strMinutes = timeZone.substring(3, 5); - final int minutes = Integer.parseInt(strMinutes); - final StringBuilder sb = new StringBuilder(); - if (minutes != 0) { - sb.append(hour, 1, hour.length()); - strMinutes = String.valueOf((double) minutes / 60); - strMinutes = strMinutes.substring(1); - sb.append(strMinutes); - } - else { - sb.append(hour); - } - setExpectedAlerts(sb.toString()); - loadPageVerifyTitle2(html); - } - /** * @throws Exception if the test fails */ diff --git a/src/test/java/org/htmlunit/javascript/JavaScriptEngine2Test.java b/src/test/java/org/htmlunit/javascript/JavaScriptEngine2Test.java index c88853faa79..4128ea533d4 100644 --- a/src/test/java/org/htmlunit/javascript/JavaScriptEngine2Test.java +++ b/src/test/java/org/htmlunit/javascript/JavaScriptEngine2Test.java @@ -1123,6 +1123,33 @@ public void constInOfLoop() throws Exception { loadPageVerifyTitle2(html); } + /** + * @throws Exception if the test fails + */ + @Test + @Alerts("seven") + public void constInIfElse() throws Exception { + final String html = "\n" + + "\n" + + "\n" + + "\n" + + ""; + + loadPageVerifyTitle2(html); + } + /** * @throws Exception if the test fails */ diff --git a/src/test/java/org/htmlunit/javascript/NativeDate2Test.java b/src/test/java/org/htmlunit/javascript/NativeDate2Test.java new file mode 100644 index 00000000000..fd0290b24db --- /dev/null +++ b/src/test/java/org/htmlunit/javascript/NativeDate2Test.java @@ -0,0 +1,766 @@ +/* + * Copyright (c) 2002-2024 Gargoyle Software Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.htmlunit.javascript; + +import java.util.TimeZone; + +import org.htmlunit.BrowserVersion; +import org.htmlunit.WebDriverTestCase; +import org.htmlunit.junit.BrowserRunner; +import org.htmlunit.junit.BrowserRunner.Alerts; +import org.htmlunit.junit.BrowserRunner.BuggyWebDriver; +import org.htmlunit.junit.BrowserRunner.HtmlUnitNYI; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Test for the Date support. + * + * @author Ronald Brill + */ +@RunWith(BrowserRunner.class) +public class NativeDate2Test extends WebDriverTestCase { + + @Test + @Alerts("2021-12-18T22:23:00.000Z") + public void ctorDateTimeStringGMT() throws Exception { + ctorDateTimeString("new Date('2021-12-18T22:23:00.000+00:00').toISOString()"); + } + + @Test + @Alerts("2021-12-18T22:23:00.000Z") + public void ctorDateTimeStringGMT2() throws Exception { + ctorDateTimeString("new Date('Sat, 18 Dec 2021 22:23:00 GMT').toISOString()"); + } + + @Test + @Alerts("2021-12-18T22:23:00.000Z") + public void ctorDateTimeStringUTC() throws Exception { + ctorDateTimeString("new Date('2021-12-18T22:23:00.000+00:00').toISOString()"); + } + + @Test + @Alerts("2021-12-18T22:23:00.000Z") + public void ctorDateTimeStringUTC2() throws Exception { + ctorDateTimeString("new Date('Sat, 18 Dec 2021 22:23:00 UTC').toISOString()"); + } + + @Test + @Alerts("2021-12-18T22:23:00.000Z") + public void ctorDateTimeStringUT() throws Exception { + ctorDateTimeString("new Date('Sat, 18 Dec 2021 22:23:00 UT').toISOString()"); + } + + @Test + @Alerts("2021-12-18T12:23:00.000Z") + public void ctorDateTimeStringEST() throws Exception { + ctorDateTimeString("new Date('2021-12-18T17:23:00.000+05:00').toISOString()"); + } + + @Test + @Alerts("2021-12-19T03:23:00.000Z") + public void ctorDateTimeStringEST2() throws Exception { + ctorDateTimeString("new Date('Sat, 18 Dec 2021 22:23:00 EST').toISOString()"); + } + + @Test + @Alerts("2021-12-19T02:23:00.000Z") + public void ctorDateTimeStringEDT() throws Exception { + ctorDateTimeString("new Date('Sat, 18 Dec 2021 22:23:00 EDT').toISOString()"); + } + + @Test + @Alerts("2021-12-19T04:23:00.000Z") + public void ctorDateTimeStringCST() throws Exception { + ctorDateTimeString("new Date('Sat, 18 Dec 2021 22:23:00 CST').toISOString()"); + } + + @Test + @Alerts("2021-12-19T03:23:00.000Z") + public void ctorDateTimeStringCDT() throws Exception { + ctorDateTimeString("new Date('Sat, 18 Dec 2021 22:23:00 CDT').toISOString()"); + } + + @Test + @Alerts("2021-12-19T05:23:00.000Z") + public void ctorDateTimeStringMST() throws Exception { + ctorDateTimeString("new Date('Sat, 18 Dec 2021 22:23:00 MST').toISOString()"); + } + + @Test + @Alerts("2021-12-19T04:23:00.000Z") + public void ctorDateTimeStringMDT() throws Exception { + ctorDateTimeString("new Date('Sat, 18 Dec 2021 22:23:00 MDT').toISOString()"); + } + + @Test + @Alerts("2021-12-19T06:23:00.000Z") + public void ctorDateTimeStringPST() throws Exception { + ctorDateTimeString("new Date('Sat, 18 Dec 2021 22:23:00 PST').toISOString()"); + } + + @Test + @Alerts("2021-12-19T05:23:00.000Z") + public void ctorDateTimeStringPDT() throws Exception { + ctorDateTimeString("new Date('Sat, 18 Dec 2021 22:23:00 PDT').toISOString()"); + } + + @Test + @Alerts("2021-12-18T18:23:00.000Z") + public void ctorDateTimeStringBerlin() throws Exception { + ctorDateTimeString("new Date('2021-12-18T17:23:00.000-01:00').toISOString()"); + } + + @Test + @Alerts("2021-12-19T02:23:00.000Z") + public void ctorDateTimeStringTokyo() throws Exception { + ctorDateTimeString("new Date('2021-12-18T17:23:00.000-09:00').toISOString()"); + } + + @Test + @Alerts("2021-12-19T02:23:00.000Z") + public void ctorDateTimeStringJST() throws Exception { + ctorDateTimeString("new Date('2021-12-18T17:23:00.000-09:00').toISOString()"); + } + + @Test + @Alerts("2021-12-18T12:23:00.000Z") + public void ctorDateTimeStringNewYork() throws Exception { + ctorDateTimeString("new Date('2021-12-18T17:23:00.000+05:00').toISOString()"); + } + + private void ctorDateTimeString(final String js) throws Exception { + final String html + = "\n" + + ""; + + loadPageVerifyTitle2(html); + } + + @Test + @Alerts("2021-12-18T22:23:00.000Z") + @BuggyWebDriver(FF = "2021-12-18T21:23:00.000Z", + FF_ESR = "2021-12-18T21:23:00.000Z") + public void ctorDateTimeGMT() throws Exception { + ctorDateTime("GMT"); + } + + @Test + @Alerts("2021-12-18T22:23:00.000Z") + @BuggyWebDriver(FF = "2021-12-18T21:23:00.000Z", + FF_ESR = "2021-12-18T21:23:00.000Z") + public void ctorDateTimeUTC() throws Exception { + ctorDateTime("UTC"); + } + + @Test + @Alerts("2021-12-19T03:23:00.000Z") + @BuggyWebDriver(FF = "2021-12-18T21:23:00.000Z", + FF_ESR = "2021-12-18T21:23:00.000Z") + public void ctorDateTimeEST() throws Exception { + ctorDateTime("EST"); + } + + @Test + @Alerts("2021-12-18T21:23:00.000Z") + public void ctorDateTimeBerlin() throws Exception { + ctorDateTime("Europe/Berlin"); + } + + @Test + @Alerts("2021-12-18T13:23:00.000Z") + @BuggyWebDriver(FF = "2021-12-18T21:23:00.000Z", + FF_ESR = "2021-12-18T21:23:00.000Z") + public void ctorDateTimeTokyo() throws Exception { + ctorDateTime("Asia/Tokyo"); + } + + @Test + @Alerts("2021-12-18T13:23:00.000Z") + @BuggyWebDriver(FF = "2021-12-18T21:23:00.000Z", + FF_ESR = "2021-12-18T21:23:00.000Z") + public void ctorDateTimeJST() throws Exception { + ctorDateTime("JST"); + } + + @Test + @Alerts("2021-12-19T03:23:00.000Z") + @BuggyWebDriver(FF = "2021-12-18T21:23:00.000Z", + FF_ESR = "2021-12-18T21:23:00.000Z") + public void ctorDateTimeNewYork() throws Exception { + ctorDateTime("America/New_York"); + } + + private void ctorDateTime(final String tz) throws Exception { + final String html + = "\n" + + ""; + + shutDownAll(); + try { + final BrowserVersion.BrowserVersionBuilder builder + = new BrowserVersion.BrowserVersionBuilder(getBrowserVersion()); + builder.setSystemTimezone(TimeZone.getTimeZone(tz)); + setBrowserVersion(builder.build()); + + loadPageVerifyTitle2(html); + } + finally { + shutDownAll(); + } + } + + @Test + @Alerts("2021-12-18T00:00:00.000Z") + public void ctorDateGMT() throws Exception { + ctorDate("GMT"); + } + + @Test + @Alerts("2021-12-18T00:00:00.000Z") + public void ctorDateUTC() throws Exception { + ctorDate("UTC"); + } + + @Test + @Alerts("2021-12-18T00:00:00.000Z") + public void ctorDateEST() throws Exception { + ctorDate("EST"); + } + + @Test + @Alerts("2021-12-18T00:00:00.000Z") + public void ctorDateBerlin() throws Exception { + ctorDate("Europe/Berlin"); + } + + @Test + @Alerts("2021-12-18T00:00:00.000Z") + public void ctorDateNewYork() throws Exception { + ctorDate("America/New_York"); + } + + @Test + @Alerts("2021-12-18T00:00:00.000Z") + public void ctorDateTokyo() throws Exception { + ctorDate("Asia/Tokyo"); + } + + @Test + @Alerts("2021-12-18T00:00:00.000Z") + public void ctorDateJST() throws Exception { + ctorDate("JST"); + } + + private void ctorDate(final String tz) throws Exception { + final String html + = "\n" + + ""; + + shutDownAll(); + try { + final BrowserVersion.BrowserVersionBuilder builder + = new BrowserVersion.BrowserVersionBuilder(getBrowserVersion()); + builder.setSystemTimezone(TimeZone.getTimeZone(tz)); + setBrowserVersion(builder.build()); + + loadPageVerifyTitle2(html); + } + finally { + shutDownAll(); + } + } + + @Test + @Alerts("2000-02-28T23:59:59.000Z") + public void ctorInt() throws Exception { + final String html + = "\n" + + ""; + + loadPageVerifyTitle2(html); + } + + @Test + @Alerts("2035-11-30T01:46:40.000Z") + public void ctorDouble() throws Exception { + final String html + = "\n" + + ""; + + loadPageVerifyTitle2(html); + } + + @Test + @Alerts("12/18/2021, 10:23:00 PM") + @HtmlUnitNYI(CHROME = "12/18/21, 10:23 PM", + EDGE = "12/18/21, 10:23 PM", + FF = "12/18/21, 10:23 PM", + FF_ESR = "12/18/21, 10:23 PM") + public void toLocaleEnUs() throws Exception { + toLocale("new Date('2021-12-18T22:23').toLocaleString('en-US')"); + } + + @Test + @Alerts("12/18/2021") + @HtmlUnitNYI(CHROME = "12/18/21", + EDGE = "12/18/21", + FF = "12/18/21", + FF_ESR = "12/18/21") + public void toLocaleEnUsDate() throws Exception { + toLocale("new Date('2021-12-18T22:23').toLocaleDateString('en-US')"); + } + + @Test + @Alerts("10:23:00 PM") + @HtmlUnitNYI(CHROME = "10:23 PM", + EDGE = "10:23 PM", + FF = "10:23 PM", + FF_ESR = "10:23 PM") + public void toLocaleEnUsTime() throws Exception { + toLocale("new Date('2021-12-18T22:23').toLocaleTimeString('en-US')"); + } + + @Test + @Alerts("18.12.2021, 22:23:00") + @HtmlUnitNYI(CHROME = "18.12.21, 22:23", + EDGE = "18.12.21, 22:23", + FF = "18.12.21, 22:23", + FF_ESR = "18.12.21, 22:23") + public void toLocaleDeDe() throws Exception { + toLocale("new Date('2021-12-18T22:23').toLocaleString('de-DE')"); + } + + @Test + @Alerts("18.12.2021") + @HtmlUnitNYI(CHROME = "18.12.21", + EDGE = "18.12.21", + FF = "18.12.21", + FF_ESR = "18.12.21") + public void toLocaleDeDeDate() throws Exception { + toLocale("new Date('2021-12-18T22:23').toLocaleDateString('de-DE')"); + } + + @Test + @Alerts("22:23:00") + @HtmlUnitNYI(CHROME = "22:23", + EDGE = "22:23", + FF = "22:23", + FF_ESR = "22:23") + public void toLocaleDeDeTime() throws Exception { + toLocale("new Date('2021-12-18T22:23').toLocaleTimeString('de-DE')"); + } + + @Test + @Alerts("2021/12/18 22:23:00") + @HtmlUnitNYI(CHROME = "2021/12/18 22:23", + EDGE = "2021/12/18 22:23", + FF = "2021/12/18 22:23", + FF_ESR = "2021/12/18 22:23") + public void toLocaleJaJp() throws Exception { + toLocale("new Date('2021-12-18T22:23').toLocaleString('ja-JP')"); + } + + @Test + @Alerts("2021/12/18") + public void toLocaleJaJpDate() throws Exception { + toLocale("new Date('2021-12-18T22:23').toLocaleDateString('ja-JP')"); + } + + @Test + @Alerts("22:23:00") + @HtmlUnitNYI(CHROME = "22:23", + EDGE = "22:23", + FF = "22:23", + FF_ESR = "22:23") + public void toLocaleJaJpTime() throws Exception { + toLocale("new Date('2021-12-18T22:23').toLocaleTimeString('ja-JP')"); + } + + @Test + @Alerts("2021/12/18 22:23:00") + @HtmlUnitNYI(CHROME = "2021/12/18 22:23", + EDGE = "2021/12/18 22:23", + FF = "2021/12/18 22:23", + FF_ESR = "2021/12/18 22:23") + public void toLocaleArray() throws Exception { + toLocale("new Date('2021-12-18T22:23').toLocaleString(['foo', 'ja-JP', 'en-US'])"); + } + + @Test + @Alerts("2021/12/18") + public void toLocaleArrayDate() throws Exception { + toLocale("new Date('2021-12-18T22:23').toLocaleDateString(['foo', 'ja-JP', 'en-US'])"); + } + + @Test + @Alerts("22:23:00") + @HtmlUnitNYI(CHROME = "22:23", + EDGE = "22:23", + FF = "22:23", + FF_ESR = "22:23") + public void toLocaleArrayTime() throws Exception { + toLocale("new Date('2021-12-18T22:23').toLocaleTimeString(['foo', 'ja-JP', 'en-US'])"); + } + + private void toLocale(final String js) throws Exception { + final String html + = "\n" + + ""; + + shutDownAll(); + try { + final BrowserVersion.BrowserVersionBuilder builder + = new BrowserVersion.BrowserVersionBuilder(getBrowserVersion()); + builder.setSystemTimezone(TimeZone.getTimeZone("GMT")); + setBrowserVersion(builder.build()); + + loadPageVerifyTitle2(html); + } + finally { + shutDownAll(); + } + } + + @Test + @Alerts("Sat Dec 18 2021") + public void toDateStringGMT() throws Exception { + toDateString("GMT"); + } + + @Test + @Alerts("Sat Dec 18 2021") + public void toDateStringUTC() throws Exception { + toDateString("UTC"); + } + + @Test + @Alerts("Sat Dec 18 2021") + public void toDateStringEST() throws Exception { + toDateString("EST"); + } + + @Test + @Alerts("Sat Dec 18 2021") + public void toDateStringBerlin() throws Exception { + toDateString("Europe/Berlin"); + } + + @Test + @Alerts("Sat Dec 18 2021") + public void toDateStringNewYork() throws Exception { + toDateString("America/New_York"); + } + + @Test + @Alerts("Sun Dec 19 2021") + @BuggyWebDriver(FF = "Sat Dec 18 2021", + FF_ESR = "Sat Dec 18 2021") + public void toDateStringTokyo() throws Exception { + toDateString("Asia/Tokyo"); + } + + @Test + @Alerts("Sun Dec 19 2021") + @BuggyWebDriver(FF = "Sat Dec 18 2021", + FF_ESR = "Sat Dec 18 2021") + public void toDateStringJST() throws Exception { + toDateString("JST"); + } + + private void toDateString(final String tz) throws Exception { + final String html + = "\n" + + ""; + + shutDownAll(); + try { + final BrowserVersion.BrowserVersionBuilder builder + = new BrowserVersion.BrowserVersionBuilder(getBrowserVersion()); + builder.setSystemTimezone(TimeZone.getTimeZone(tz)); + setBrowserVersion(builder.build()); + + loadPageVerifyTitle2(html); + } + finally { + shutDownAll(); + } + } + + @Test + @Alerts("22:23:00 GMT+0000 (Greenwich Mean Time)") + @BuggyWebDriver(FF = "23:23:00 GMT+0100 (Central European Standard Time)", + FF_ESR = "23:23:00 GMT+0100 (Central European Standard Time)") + @HtmlUnitNYI(CHROME = "22:23:00 GMT-0000 (GMT)", + EDGE = "22:23:00 GMT-0000 (GMT)", + FF = "22:23:00 GMT-0000 (GMT)", + FF_ESR = "22:23:00 GMT-0000 (GMT)") + public void toTimeStringGMT() throws Exception { + toTimeString("GMT"); + } + + @Test + @Alerts("22:23:00 GMT+0000 (Coordinated Universal Time)") + @BuggyWebDriver(FF = "23:23:00 GMT+0100 (Central European Standard Time)", + FF_ESR = "23:23:00 GMT+0100 (Central European Standard Time)") + @HtmlUnitNYI(CHROME = "22:23:00 GMT-0000 (UTC)", + EDGE = "22:23:00 GMT-0000 (UTC)", + FF = "22:23:00 GMT-0000 (UTC)", + FF_ESR = "22:23:00 GMT-0000 (UTC)") + public void toTimeStringUTC() throws Exception { + toTimeString("UTC"); + } + + @Test + @Alerts("17:23:00 GMT-0500 (GMT-05:00)") + @BuggyWebDriver(FF = "23:23:00 GMT+0100 (Central European Standard Time)", + FF_ESR = "23:23:00 GMT+0100 (Central European Standard Time)") + @HtmlUnitNYI(CHROME = "17:23:00 GMT-0500 (-05:00)", + EDGE = "17:23:00 GMT-0500 (-05:00)", + FF = "17:23:00 GMT-0500 (-05:00)", + FF_ESR = "17:23:00 GMT-0500 (-05:00)") + public void toTimeStringEST() throws Exception { + toTimeString("EST"); + } + + @Test + @Alerts("23:23:00 GMT+0100 (Central European Standard Time)") + @HtmlUnitNYI(CHROME = "23:23:00 GMT+0100 (CET)", + EDGE = "23:23:00 GMT+0100 (CET)", + FF = "23:23:00 GMT+0100 (CET)", + FF_ESR = "23:23:00 GMT+0100 (CET)") + public void toTimeStringBerlin() throws Exception { + toTimeString("Europe/Berlin"); + } + + @Test + @Alerts("17:23:00 GMT-0500 (Eastern Standard Time)") + @BuggyWebDriver(FF = "23:23:00 GMT+0100 (Central European Standard Time)", + FF_ESR = "23:23:00 GMT+0100 (Central European Standard Time)") + @HtmlUnitNYI(CHROME = "17:23:00 GMT-0500 (EST)", + EDGE = "17:23:00 GMT-0500 (EST)", + FF = "17:23:00 GMT-0500 (EST)", + FF_ESR = "17:23:00 GMT-0500 (EST)") + public void toTimeStringNewYork() throws Exception { + toTimeString("America/New_York"); + } + + @Test + @Alerts("07:23:00 GMT+0900 (Japan Standard Time)") + @BuggyWebDriver(FF = "23:23:00 GMT+0100 (Central European Standard Time)", + FF_ESR = "23:23:00 GMT+0100 (Central European Standard Time)") + @HtmlUnitNYI(CHROME = "07:23:00 GMT+0900 (JST)", + EDGE = "07:23:00 GMT+0900 (JST)", + FF = "07:23:00 GMT+0900 (JST)", + FF_ESR = "07:23:00 GMT+0900 (JST)") + public void toTimeStringTokyo() throws Exception { + toTimeString("Asia/Tokyo"); + } + + @Test + @Alerts("07:23:00 GMT+0900 (Japan Standard Time)") + @BuggyWebDriver(FF = "23:23:00 GMT+0100 (Central European Standard Time)", + FF_ESR = "23:23:00 GMT+0100 (Central European Standard Time)") + @HtmlUnitNYI(CHROME = "07:23:00 GMT+0900 (JST)", + EDGE = "07:23:00 GMT+0900 (JST)", + FF = "07:23:00 GMT+0900 (JST)", + FF_ESR = "07:23:00 GMT+0900 (JST)") + public void toTimeStringJST() throws Exception { + toTimeString("JST"); + } + + private void toTimeString(final String tz) throws Exception { + final String html + = "\n" + + ""; + + shutDownAll(); + try { + final BrowserVersion.BrowserVersionBuilder builder + = new BrowserVersion.BrowserVersionBuilder(getBrowserVersion()); + builder.setSystemTimezone(TimeZone.getTimeZone(tz)); + setBrowserVersion(builder.build()); + + loadPageVerifyTitle2(html); + } + finally { + shutDownAll(); + } + } + + @Test + @Alerts("Sat, 18 Dec 2021 22:23:00 GMT") + public void toUTCStringGMT() throws Exception { + toUTCString("GMT"); + } + + @Test + @Alerts("Sat, 18 Dec 2021 22:23:00 GMT") + public void toUTCStringUTC() throws Exception { + toUTCString("UTC"); + } + + @Test + @Alerts("Sat, 18 Dec 2021 22:23:00 GMT") + public void toUTCStringEST() throws Exception { + toUTCString("EST"); + } + + @Test + @Alerts("Sat, 18 Dec 2021 22:23:00 GMT") + public void toUTCStringBerlin() throws Exception { + toUTCString("Europe/Berlin"); + } + + @Test + @Alerts("Sat, 18 Dec 2021 22:23:00 GMT") + public void toUTCStringNewYork() throws Exception { + toUTCString("America/New_York"); + } + + @Test + @Alerts("Sat, 18 Dec 2021 22:23:00 GMT") + public void toUTCStringTokyo() throws Exception { + toUTCString("Asia/Tokyo"); + } + + @Test + @Alerts("Sat, 18 Dec 2021 22:23:00 GMT") + public void toUTCStringJST() throws Exception { + toUTCString("JST"); + } + + private void toUTCString(final String tz) throws Exception { + final String html + = "\n" + + ""; + + shutDownAll(); + try { + final BrowserVersion.BrowserVersionBuilder builder + = new BrowserVersion.BrowserVersionBuilder(getBrowserVersion()); + builder.setSystemTimezone(TimeZone.getTimeZone(tz)); + setBrowserVersion(builder.build()); + + loadPageVerifyTitle2(html); + } + finally { + shutDownAll(); + } + } + + @Test + @Alerts("0") + @BuggyWebDriver(FF = "-60", + FF_ESR = "-60") + public void timezoneOffsetGMT() throws Exception { + timezoneOffset("GMT"); + } + + @Test + @Alerts("0") + @BuggyWebDriver(FF = "-60", + FF_ESR = "-60") + public void timezoneOffsetUTC() throws Exception { + timezoneOffset("UTC"); + } + + @Test + @Alerts("300") + @BuggyWebDriver(FF = "-60", + FF_ESR = "-60") + public void timezoneOffsetEST() throws Exception { + timezoneOffset("EST"); + } + + @Test + @Alerts("-60") + public void timezoneOffsetBerlin() throws Exception { + timezoneOffset("Europe/Berlin"); + } + + @Test + @Alerts("300") + @BuggyWebDriver(FF = "-60", + FF_ESR = "-60") + public void timezoneOffsetNewYork() throws Exception { + timezoneOffset("America/New_York"); + } + + @Test + @Alerts("-540") + @BuggyWebDriver(FF = "-60", + FF_ESR = "-60") + public void timezoneOffsetTokyo() throws Exception { + timezoneOffset("Asia/Tokyo"); + } + + @Test + @Alerts("-540") + @BuggyWebDriver(FF = "-60", + FF_ESR = "-60") + public void timezoneOffsetJST() throws Exception { + timezoneOffset("JST"); + } + + private void timezoneOffset(final String tz) throws Exception { + final String html + = "\n" + + ""; + + shutDownAll(); + try { + final BrowserVersion.BrowserVersionBuilder builder + = new BrowserVersion.BrowserVersionBuilder(getBrowserVersion()); + builder.setSystemTimezone(TimeZone.getTimeZone(tz)); + setBrowserVersion(builder.build()); + + loadPageVerifyTitle2(html); + } + finally { + shutDownAll(); + } + } +} diff --git a/src/test/java/org/htmlunit/javascript/NativeDateTest.java b/src/test/java/org/htmlunit/javascript/NativeDateTest.java index 6c147ebe1ce..cab218760c9 100644 --- a/src/test/java/org/htmlunit/javascript/NativeDateTest.java +++ b/src/test/java/org/htmlunit/javascript/NativeDateTest.java @@ -131,25 +131,6 @@ static String createHTMLTestMethods(final String object, final String... methodN return html; } - /** - * Test for bug 1467. - * @throws Exception if the test fails - */ - @Test - @Alerts("1/1/2000") - public void toLocaleDateString() throws Exception { - final String html - = "\n" - + ""; - - loadPageVerifyTitle2(html); - } - /** * @throws Exception if the test fails */ @@ -233,28 +214,4 @@ public void enumerable() throws Exception { loadPageVerifyTitle2(html); } - - /** - * @throws Exception if the test fails - */ - @Test - @Alerts({"12:00:00 AM", "7:08:09 AM"}) - public void toLocaleTimeString() throws Exception { - final String html - = "\n" - + ""; - - loadPageVerifyTitle2(html); - } - } diff --git a/src/test/java/org/htmlunit/javascript/NativeObjectTest.java b/src/test/java/org/htmlunit/javascript/NativeObjectTest.java index 17b8de6f7a1..412865af91d 100644 --- a/src/test/java/org/htmlunit/javascript/NativeObjectTest.java +++ b/src/test/java/org/htmlunit/javascript/NativeObjectTest.java @@ -446,4 +446,30 @@ public void getOwnPropertyDescriptorGetCall() throws Exception { loadPageVerifyTextArea2(html); } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"before: [object Object]", "after: [object Object]", "true"}) + public void definePropertyUsingConsString() throws Exception { + final String html = "\n" + + "\n" + + ""; + + loadPageVerifyTitle2(html); + } } diff --git a/src/test/java/org/htmlunit/javascript/host/Location2Test.java b/src/test/java/org/htmlunit/javascript/host/Location2Test.java index b198ffb9a0f..66892cd0ac7 100644 --- a/src/test/java/org/htmlunit/javascript/host/Location2Test.java +++ b/src/test/java/org/htmlunit/javascript/host/Location2Test.java @@ -948,6 +948,28 @@ public void origin() throws Exception { verifyAlerts(driver, expectedAlerts); } + /** + * @throws Exception if the test fails + */ + @Test + @Alerts("§§ORIGIN§§") + public void documentOrigin() throws Exception { + final String html = + ""; + + final String[] expectedAlerts = getExpectedAlerts(); + final URL url = URL_FIRST; + final String origin = url.getProtocol() + "://" + url.getHost() + ':' + url.getPort(); + for (int i = 0; i < expectedAlerts.length; i++) { + expectedAlerts[i] = expectedAlerts[i].replaceAll("§§ORIGIN§§", origin); + } + + final WebDriver driver = loadPage2(html); + verifyAlerts(driver, expectedAlerts); + } + /** * @throws Exception if the test fails */ diff --git a/src/test/java/org/htmlunit/javascript/host/URLTest.java b/src/test/java/org/htmlunit/javascript/host/URLTest.java index fa281fd73f7..df3b870cedb 100644 --- a/src/test/java/org/htmlunit/javascript/host/URLTest.java +++ b/src/test/java/org/htmlunit/javascript/host/URLTest.java @@ -127,6 +127,56 @@ public void origin() throws Exception { loadPageVerifyTitle2(html); } + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts("http://developer.mozilla.org") + public void originDefaultPort() throws Exception { + final String html = + "\n" + + "\n" + + " \n" + + "\n" + + "\n" + + "\n" + + ""; + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts("http://developer.mozilla.org:1234") + public void originPort() throws Exception { + final String html = + "\n" + + "\n" + + " \n" + + "\n" + + "\n" + + "\n" + + ""; + loadPageVerifyTitle2(html); + } + /** * @throws Exception if the test fails */ diff --git a/src/test/java/org/htmlunit/javascript/host/Window2Test.java b/src/test/java/org/htmlunit/javascript/host/Window2Test.java index c7bb4494c06..68a2b6dfb5e 100644 --- a/src/test/java/org/htmlunit/javascript/host/Window2Test.java +++ b/src/test/java/org/htmlunit/javascript/host/Window2Test.java @@ -2598,16 +2598,8 @@ public void userDefinedProperty() throws Exception { * @throws Exception if the test fails */ @Test - @Alerts(DEFAULT = {"undefined", "{\"enumerable\":false,\"configurable\":true}", - "[object Event]", "{\"enumerable\":false,\"configurable\":true}"}, - FF = {"undefined", "{\"enumerable\":true,\"configurable\":true}", - "[object Event]", "{\"enumerable\":true,\"configurable\":true}"}, - FF_ESR = {"undefined", "{\"enumerable\":true,\"configurable\":true}", - "[object Event]", "{\"enumerable\":true,\"configurable\":true}"}) - @HtmlUnitNYI(CHROME = {"undefined", "{\"enumerable\":true,\"configurable\":true}", - "[object Event]", "{\"enumerable\":true,\"configurable\":true}"}, - EDGE = {"undefined", "{\"enumerable\":true,\"configurable\":true}", - "[object Event]", "{\"enumerable\":true,\"configurable\":true}"}) + @Alerts({"undefined", "{\"enumerable\":true,\"configurable\":true}", + "[object Event]", "{\"enumerable\":true,\"configurable\":true}"}) public void eventProperty() throws Exception { final String html = "\n" + "\n" + + "\n" + + "bla\n" + + "\n" + + ""; + + loadPageVerifyTitle2(content); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts({"1", "[object HTMLDivElement]"}) + public void append() throws Exception { + final String content = "\n" + + "\n" + + " \n" + + "\n" + + "bla\n" + + "\n" + + ""; + + loadPageVerifyTitle2(content); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts("0") + public void appendNoParam() throws Exception { + final String content = "\n" + + "\n" + + " \n" + + "\n" + + "bla\n" + + "\n" + + ""; + + loadPageVerifyTitle2(content); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts({"1", "[object Text]", "abcd", + "2", "[object Text]", "1234"}) + public void appendText() throws Exception { + final String content = "\n" + + "\n" + + " \n" + + "\n" + + "bla\n" + + "\n" + + ""; + + loadPageVerifyTitle2(content); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts({"1", "[object HTMLDivElement]", + "2", "[object Text]", "abcd", + "3", "[object HTMLDivElement]", + "4", "[object Text]", "1234", + "5", "[object HTMLDivElement]"}) + public void appendMixed() throws Exception { + final String content = "\n" + + "\n" + + " \n" + + "\n" + + "bla\n" + + "\n" + + ""; + + loadPageVerifyTitle2(content); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts({"1", "[object HTMLDivElement]"}) + public void prepend() throws Exception { + final String content = "\n" + + "\n" + + " \n" + + "\n" + + "bla\n" + + "\n" + + ""; + + loadPageVerifyTitle2(content); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts("0") + public void prependNoParam() throws Exception { + final String content = "\n" + + "\n" + + " \n" + + "\n" + + "bla\n" + + "\n" + + ""; + + loadPageVerifyTitle2(content); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts({"1", "[object Text]", "abcd", + "2", "[object Text]", "1234"}) + public void prependText() throws Exception { + final String content = "\n" + + "\n" + + " \n" + + "\n" + + "bla\n" + + "\n" + + ""; + + loadPageVerifyTitle2(content); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts({"1", "[object HTMLDivElement]", + "2", "[object Text]", "abcd", + "3", "[object HTMLDivElement]", + "4", "[object Text]", "1234", + "5", "[object HTMLDivElement]"}) + public void prependMixed() throws Exception { + final String content = "\n" + + "\n" + + " \n" + + "\n" + + "bla\n" + + "\n" + + ""; + + loadPageVerifyTitle2(content); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts({"1", "[object HTMLDivElement]"}) + public void replaceChildren() throws Exception { + final String content = "\n" + + "\n" + + " \n" + + "\n" + + "bla\n" + + "\n" + + ""; + + loadPageVerifyTitle2(content); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts("0") + public void replaceChildrenNoParam() throws Exception { + final String content = "\n" + + "\n" + + " \n" + + "\n" + + "bla\n" + + "\n" + + ""; + + loadPageVerifyTitle2(content); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts({"1", "[object Text]", "abcd", + "1", "[object Text]", "1234"}) + public void replaceChildrenText() throws Exception { + final String content = "\n" + + "\n" + + " \n" + + "\n" + + "bla\n" + + "\n" + + ""; + + loadPageVerifyTitle2(content); + } + + /** + * @throws Exception on test failure + */ + @Test + @Alerts({"1", "[object HTMLDivElement]", + "1", "[object Text]", "abcd", + "1", "[object HTMLDivElement]", + "1", "[object Text]", "1234", + "1", "[object HTMLDivElement]"}) + public void replaceChildrenMixed() throws Exception { + final String content = "\n" + + "\n" + + " \n" + + "\n" + + "bla\n" + + "\n" + + ""; + + loadPageVerifyTitle2(content); + } } diff --git a/src/test/java/org/htmlunit/javascript/host/dom/XPathEvaluatorTest.java b/src/test/java/org/htmlunit/javascript/host/dom/XPathEvaluatorTest.java index aad3cfeeb14..c2c6f14adf2 100644 --- a/src/test/java/org/htmlunit/javascript/host/dom/XPathEvaluatorTest.java +++ b/src/test/java/org/htmlunit/javascript/host/dom/XPathEvaluatorTest.java @@ -35,7 +35,7 @@ public class XPathEvaluatorTest extends WebDriverTestCase { */ @Test @Alerts({"function", "[object XPathEvaluator]", "[object HTMLHtmlElement]", "first", "second", ""}) - public void simple() throws Exception { + public void evaluate() throws Exception { final String html = "\n" + "hello\n" + "
    world
    \n" @@ -61,6 +61,99 @@ public void simple() throws Exception { loadPageVerifyTitle2(html); } + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"function", "[object XPathEvaluator]", "[object HTMLHtmlElement]", "first", "second", ""}) + public void evaluateWithoutResult() throws Exception { + final String html = "\n" + + "hello\n" + + "
    world
    \n" + + ""; + + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"function", "[object XPathEvaluator]", "[object HTMLHtmlElement]", "first", "second", ""}) + public void evaluateWithoutTypeResult() throws Exception { + final String html = "\n" + + "hello\n" + + "
    world
    \n" + + ""; + + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"function", "[object XPathEvaluator]", "[object HTMLHtmlElement]", "first", "second", ""}) + public void evaluateWithoutResolverTypeResult() throws Exception { + final String html = "\n" + + "hello\n" + + "
    world
    \n" + + ""; + + loadPageVerifyTitle2(html); + } + /** * @throws Exception if the test fails */ @@ -139,4 +232,106 @@ public void namespacesWithCustomNSResolver() throws Exception { loadPageVerifyTitle2(html); } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts("exception") + public void createExpressionNoXPath() throws Exception { + final String html = "\n" + + ""; + + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"function", "[object XPathEvaluator]", "[object XPathExpression]§"}) + public void createExpressionUndefinedXPath() throws Exception { + final String html = "\n" + + "hello\n" + + "
    world
    \n" + + ""; + + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"function", "[object XPathEvaluator]", "[object XPathExpression]§"}) + public void createExpressionNullXPath() throws Exception { + final String html = "\n" + + "hello\n" + + "
    world
    \n" + + ""; + + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts("SyntaxError") + public void createExpressionInvalid() throws Exception { + final String html = "\n" + + ""; + + loadPageVerifyTitle2(html); + } } diff --git a/src/test/java/org/htmlunit/javascript/host/dom/XPathExpressionTest.java b/src/test/java/org/htmlunit/javascript/host/dom/XPathExpressionTest.java new file mode 100644 index 00000000000..270b9c98a65 --- /dev/null +++ b/src/test/java/org/htmlunit/javascript/host/dom/XPathExpressionTest.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2002-2024 Gargoyle Software Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.htmlunit.javascript.host.dom; + +import org.htmlunit.WebDriverTestCase; +import org.htmlunit.junit.BrowserRunner; +import org.htmlunit.junit.BrowserRunner.Alerts; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Tests for {@link XPathExpression}. + * + * @author Ronald Brill + */ +@RunWith(BrowserRunner.class) +public class XPathExpressionTest extends WebDriverTestCase { + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"function", "[object XPathEvaluator]", "[object XPathExpression]", "first", "second", ""}) + public void simple() throws Exception { + final String html = "\n" + + "hello\n" + + "
    world
    \n" + + ""; + + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"function", "[object HTMLHtmlElement]", "[object XPathEvaluator]", + "[object XPathExpression]", "first", "second", ""}) + public void withResolver() throws Exception { + final String html = "\n" + + "hello\n" + + "
    world
    \n" + + ""; + + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"function", "[object HTMLHtmlElement]", "[object XPathEvaluator]", + "[object XPathExpression]", "exception", ""}) + public void evaluateContextNode() throws Exception { + final String html = "\n" + + "hello\n" + + "
    world
    \n" + + ""; + + loadPageVerifyTitle2(html); + } +} diff --git a/src/test/java/org/htmlunit/javascript/host/file/FileTest.java b/src/test/java/org/htmlunit/javascript/host/file/FileTest.java index ce604c3a6a8..53abb9e06a4 100644 --- a/src/test/java/org/htmlunit/javascript/host/file/FileTest.java +++ b/src/test/java/org/htmlunit/javascript/host/file/FileTest.java @@ -17,8 +17,11 @@ import static java.nio.charset.StandardCharsets.ISO_8859_1; import java.io.File; +import java.util.Locale; +import java.util.TimeZone; import org.apache.commons.io.FileUtils; +import org.htmlunit.BrowserVersion; import org.htmlunit.WebDriverTestCase; import org.htmlunit.html.HtmlPageTest; import org.htmlunit.junit.BrowserRunner; @@ -431,4 +434,122 @@ public void ctorMixed() throws Exception { loadPage2(html); verifyTitle2(DEFAULT_WAIT_TIME, getWebDriver(), getExpectedAlerts()); } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "Sun Jul 26 2015 10:21:47 GMT-0400 (Eastern Daylight Time)", + FF = "undefined", + FF_ESR = "undefined") + public void lastModifiedDate() throws Exception { + lastModifiedDate(getBrowserVersion().getSystemTimezone().getID(), getBrowserVersion().getBrowserLocale()); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "Sun Jul 26 2015 14:21:47 GMT+0000 (Greenwich Mean Time)", + FF = "undefined", + FF_ESR = "undefined") + public void lastModifiedDateGMT() throws Exception { + lastModifiedDate("GMT", getBrowserVersion().getBrowserLocale()); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "Sun Jul 26 2015 14:21:47 GMT+0000 (Coordinated Universal Time)", + FF = "undefined", + FF_ESR = "undefined") + public void lastModifiedDateUTC() throws Exception { + lastModifiedDate("UTC", getBrowserVersion().getBrowserLocale()); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "Sun Jul 26 2015 16:21:47 GMT+0200 (Mitteleuropäische Sommerzeit)", + FF = "undefined", + FF_ESR = "undefined") + public void lastModifiedDateBerlin() throws Exception { + lastModifiedDate("Europe/Berlin", Locale.GERMANY); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "Sun Jul 26 2015 23:21:47 GMT+0900 (日本標準時)", + FF = "undefined", + FF_ESR = "undefined") + public void lastModifiedDateJST() throws Exception { + lastModifiedDate("JST", Locale.JAPAN); + } + + private void lastModifiedDate(final String tz, final Locale locale) throws Exception { + final String html + = HtmlPageTest.STANDARDS_MODE_PREFIX_ + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "
    \n" + + " \n" + + "
    \n" + + " \n" + + "\n" + + ""; + + final File tstFile = File.createTempFile("HtmlUnitUploadTest", ".txt"); + try { + FileUtils.writeStringToFile(tstFile, "Hello HtmlUnit", ISO_8859_1); + + // do not use millis here because different file systems + // have different precisions + assertTrue(tstFile.setLastModified(1437920507000L)); + + final String path = tstFile.getCanonicalPath(); + + shutDownAll(); + try { + final BrowserVersion.BrowserVersionBuilder builder + = new BrowserVersion.BrowserVersionBuilder(getBrowserVersion()); + builder.setSystemTimezone(TimeZone.getTimeZone(tz)); + builder.setBrowserLanguage(locale.toLanguageTag()); + setBrowserVersion(builder.build()); + + final WebDriver driver = loadPage2(html); + driver.findElement(By.name("fileupload")).sendKeys(path); + + driver.findElement(By.id("testBtn")).click(); + + final String[] expected = getExpectedAlerts(); + if (expected.length > 1) { + expected[1] = tstFile.getName(); + } + + verifyTitle2(driver, getExpectedAlerts()); + } + finally { + shutDownAll(); + } + } + finally { + FileUtils.deleteQuietly(tstFile); + } + } } diff --git a/src/test/java/org/htmlunit/javascript/host/html/HTMLDocumentTest.java b/src/test/java/org/htmlunit/javascript/host/html/HTMLDocumentTest.java index d6d87c4abf2..5aa7e8553af 100644 --- a/src/test/java/org/htmlunit/javascript/host/html/HTMLDocumentTest.java +++ b/src/test/java/org/htmlunit/javascript/host/html/HTMLDocumentTest.java @@ -26,8 +26,10 @@ import java.util.LinkedList; import java.util.List; import java.util.Locale; +import java.util.TimeZone; import org.apache.http.client.utils.DateUtils; +import org.htmlunit.BrowserVersion; import org.htmlunit.WebDriverTestCase; import org.htmlunit.html.HtmlPage; import org.htmlunit.html.HtmlPageTest; @@ -655,139 +657,6 @@ public void prefix() throws Exception { loadPageVerifyTitle2(html); } - /** - * Property lastModified returns the last modification date of the document. - * @throws Exception if the test fails - */ - @Test - @Alerts({"string", "Fri, 16 Oct 2009 13:59:47 GMT"}) - public void lastModified() throws Exception { - final List responseHeaders = new ArrayList<>(); - responseHeaders.add(new NameValuePair("Last-Modified", "Fri, 16 Oct 2009 13:59:47 GMT")); - testLastModified(responseHeaders); - - // for some strange reasons, the selenium driven browser is in an invalid - // state after this test - releaseResources(); - shutDownAll(); - } - - /** - * Property lastModified returns the last modification date of the document. - * @throws Exception if the test fails - */ - @Test - @Alerts({"string", "Fri, 16 Oct 2009 13:59:47 GMT"}) - public void lastModifiedAndDate() throws Exception { - final List responseHeaders = new ArrayList<>(); - responseHeaders.add(new NameValuePair("Last-Modified", "Fri, 16 Oct 2009 13:59:47 GMT")); - testLastModified(responseHeaders); - - // Last-Modified header has priority compared to Date header - responseHeaders.add(new NameValuePair("Date", "Fri, 17 Oct 2009 13:59:47 GMT")); - testLastModified(responseHeaders); - - // for some strange reasons, the selenium driven browser is in an invalid - // state after this test - releaseResources(); - shutDownAll(); - } - - /** - * Property lastModified returns the last modification date of the document. - * @throws Exception if the test fails - */ - @Test - @Alerts({"string", "§§URL§§"}) - public void lastModifiedOnlyDate() throws Exception { - final List responseHeaders = new ArrayList<>(); - responseHeaders.clear(); - responseHeaders.add(new NameValuePair("Date", "Fri, 16 Oct 2009 13:59:47 GMT")); - - expandExpectedAlertsVariables(DateUtils.formatDate(new Date()).substring(0, 17)); - final String html = "\n" - + "\n" - + ""; - - getMockWebConnection().setResponse(URL_FIRST, html, 200, "OK", MimeType.TEXT_HTML, responseHeaders); - - final WebDriver driver = loadPage2(URL_FIRST, ISO_8859_1); - verifyTitle2(driver, getExpectedAlerts()); - - // for some strange reasons, the selenium driven browser is in an invalid - // state after this test - releaseResources(); - shutDownAll(); - } - - private void testLastModified(final List responseHeaders) throws Exception { - final String html = "\n" - + "\n" - + ""; - - getMockWebConnection().setResponse(URL_FIRST, html, 200, "OK", MimeType.TEXT_HTML, responseHeaders); - - final WebDriver driver = loadPage2(URL_FIRST, ISO_8859_1); - verifyTitle2(driver, getExpectedAlerts()); - } - - /** - * If neither Date header nor Last-Modified header is present, current time is taken. - * @throws Exception if the test fails - */ - @Test - @Alerts({"true", "true"}) - public void lastModified_noDateHeader() throws Exception { - final String html = "\n" - + "\n" - + ""; - - loadPageVerifyTitle2(html); - } - - /** - * Regression test for bug 2919853 (format of document.lastModified was incorrect). - * @throws Exception if an error occurs - */ - @Test - public void lastModified_format() throws Exception { - final String html - = "\n" - + ""; - - final WebDriver driver = loadPageWithAlerts2(html); - final String lastModified = driver.findElement(By.id("i")).getAttribute("value"); - - try { - new SimpleDateFormat("MM/dd/yyyy HH:mm:ss", Locale.ROOT).parse(lastModified); - } - catch (final ParseException e) { - fail(e.getMessage()); - } - } - /** * Warning: this test works fine in real FF8 when started manually but fails through WebDriver. * Warning: opens a modal panel when run through IEDriver which needs to be closed MANUALLY. @@ -3046,4 +2915,261 @@ public void setBodyFrameset() throws Exception { loadPageVerifyTitle2(html); } + + /** + * Property lastModified returns the last modification date of the document. + * @throws Exception if the test fails + */ + @Test + @Alerts({"string", "10/16/2009 09:59:47", "Fri, 16 Oct 2009 13:59:47 GMT"}) + @BuggyWebDriver(FF = {"string", "10/16/2009 15:59:47", "Fri, 16 Oct 2009 13:59:47 GMT"}, + FF_ESR = {"string", "10/16/2009 15:59:47", "Fri, 16 Oct 2009 13:59:47 GMT"}) + public void lastModified() throws Exception { + final List responseHeaders = new ArrayList<>(); + responseHeaders.add(new NameValuePair("Last-Modified", "Fri, 16 Oct 2009 13:59:47 GMT")); + testLastModified(responseHeaders, getBrowserVersion().getSystemTimezone().getID()); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"string", "10/16/2009 13:59:47", "Fri, 16 Oct 2009 13:59:47 GMT"}) + @BuggyWebDriver(FF = {"string", "10/16/2009 15:59:47", "Fri, 16 Oct 2009 13:59:47 GMT"}, + FF_ESR = {"string", "10/16/2009 15:59:47", "Fri, 16 Oct 2009 13:59:47 GMT"}) + public void lastModifiedGMT() throws Exception { + final List responseHeaders = new ArrayList<>(); + responseHeaders.add(new NameValuePair("Last-Modified", "Fri, 16 Oct 2009 13:59:47 GMT")); + testLastModified(responseHeaders, "GMT"); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"string", "10/16/2009 13:59:47", "Fri, 16 Oct 2009 13:59:47 GMT"}) + @BuggyWebDriver(FF = {"string", "10/16/2009 15:59:47", "Fri, 16 Oct 2009 13:59:47 GMT"}, + FF_ESR = {"string", "10/16/2009 15:59:47", "Fri, 16 Oct 2009 13:59:47 GMT"}) + public void lastModifiedUTC() throws Exception { + final List responseHeaders = new ArrayList<>(); + responseHeaders.add(new NameValuePair("Last-Modified", "Fri, 16 Oct 2009 13:59:47 GMT")); + testLastModified(responseHeaders, "UTC"); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"string", "10/16/2009 15:59:47", "Fri, 16 Oct 2009 13:59:47 GMT"}) + @BuggyWebDriver(FF = {"string", "10/16/2009 15:59:47", "Fri, 16 Oct 2009 13:59:47 GMT"}, + FF_ESR = {"string", "10/16/2009 15:59:47", "Fri, 16 Oct 2009 13:59:47 GMT"}) + public void lastModifiedBerlin() throws Exception { + final List responseHeaders = new ArrayList<>(); + responseHeaders.add(new NameValuePair("Last-Modified", "Fri, 16 Oct 2009 13:59:47 GMT")); + testLastModified(responseHeaders, "Europe/Berlin"); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"string", "10/16/2009 22:59:47", "Fri, 16 Oct 2009 13:59:47 GMT"}) + @BuggyWebDriver(FF = {"string", "10/16/2009 15:59:47", "Fri, 16 Oct 2009 13:59:47 GMT"}, + FF_ESR = {"string", "10/16/2009 15:59:47", "Fri, 16 Oct 2009 13:59:47 GMT"}) + public void lastModifiedJST() throws Exception { + final List responseHeaders = new ArrayList<>(); + responseHeaders.add(new NameValuePair("Last-Modified", "Fri, 16 Oct 2009 13:59:47 GMT")); + testLastModified(responseHeaders, "JST"); + } + + /** + * Property lastModified returns the last modification date of the document. + * @throws Exception if the test fails + */ + @Test + @Alerts({"string", "10/16/2009 09:59:47", "Fri, 16 Oct 2009 13:59:47 GMT"}) + @BuggyWebDriver(FF = {"string", "10/16/2009 15:59:47", "Fri, 16 Oct 2009 13:59:47 GMT"}, + FF_ESR = {"string", "10/16/2009 15:59:47", "Fri, 16 Oct 2009 13:59:47 GMT"}) + public void lastModifiedAndDate() throws Exception { + final List responseHeaders = new ArrayList<>(); + responseHeaders.add(new NameValuePair("Last-Modified", "Fri, 16 Oct 2009 13:59:47 GMT")); + testLastModified(responseHeaders, getBrowserVersion().getSystemTimezone().getID()); + + // Last-Modified header has priority compared to Date header + responseHeaders.add(new NameValuePair("Date", "Fri, 17 Oct 2009 13:59:47 GMT")); + testLastModified(responseHeaders, getBrowserVersion().getSystemTimezone().getID()); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"string", "10/16/2009 13:59:47", "Fri, 16 Oct 2009 13:59:47 GMT"}) + @BuggyWebDriver(FF = {"string", "10/16/2009 15:59:47", "Fri, 16 Oct 2009 13:59:47 GMT"}, + FF_ESR = {"string", "10/16/2009 15:59:47", "Fri, 16 Oct 2009 13:59:47 GMT"}) + public void lastModifiedAndDateGMT() throws Exception { + final List responseHeaders = new ArrayList<>(); + responseHeaders.add(new NameValuePair("Last-Modified", "Fri, 16 Oct 2009 13:59:47 GMT")); + testLastModified(responseHeaders, "GMT"); + + // Last-Modified header has priority compared to Date header + responseHeaders.add(new NameValuePair("Date", "Fri, 17 Oct 2009 13:59:47 GMT")); + testLastModified(responseHeaders, "GMT"); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"string", "10/16/2009 13:59:47", "Fri, 16 Oct 2009 13:59:47 GMT"}) + @BuggyWebDriver(FF = {"string", "10/16/2009 15:59:47", "Fri, 16 Oct 2009 13:59:47 GMT"}, + FF_ESR = {"string", "10/16/2009 15:59:47", "Fri, 16 Oct 2009 13:59:47 GMT"}) + public void lastModifiedAndDateUTC() throws Exception { + final List responseHeaders = new ArrayList<>(); + responseHeaders.add(new NameValuePair("Last-Modified", "Fri, 16 Oct 2009 13:59:47 GMT")); + testLastModified(responseHeaders, "UTC"); + + // Last-Modified header has priority compared to Date header + responseHeaders.add(new NameValuePair("Date", "Fri, 17 Oct 2009 13:59:47 GMT")); + testLastModified(responseHeaders, "UTC"); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"string", "10/16/2009 15:59:47", "Fri, 16 Oct 2009 13:59:47 GMT"}) + public void lastModifiedAndDateBerlin() throws Exception { + final List responseHeaders = new ArrayList<>(); + responseHeaders.add(new NameValuePair("Last-Modified", "Fri, 16 Oct 2009 13:59:47 GMT")); + testLastModified(responseHeaders, "Europe/Berlin"); + + // Last-Modified header has priority compared to Date header + responseHeaders.add(new NameValuePair("Date", "Fri, 17 Oct 2009 13:59:47 GMT")); + testLastModified(responseHeaders, "Europe/Berlin"); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"string", "10/16/2009 22:59:47", "Fri, 16 Oct 2009 13:59:47 GMT"}) + @BuggyWebDriver(FF = {"string", "10/16/2009 15:59:47", "Fri, 16 Oct 2009 13:59:47 GMT"}, + FF_ESR = {"string", "10/16/2009 15:59:47", "Fri, 16 Oct 2009 13:59:47 GMT"}) + public void lastModifiedAndDateJST() throws Exception { + final List responseHeaders = new ArrayList<>(); + responseHeaders.add(new NameValuePair("Last-Modified", "Fri, 16 Oct 2009 13:59:47 GMT")); + testLastModified(responseHeaders, "JST"); + + // Last-Modified header has priority compared to Date header + responseHeaders.add(new NameValuePair("Date", "Fri, 17 Oct 2009 13:59:47 GMT")); + testLastModified(responseHeaders, "JST"); + } + + /** + * Property lastModified returns the last modification date of the document. + * @throws Exception if the test fails + */ + @Test + @Alerts({"string", "§§URL§§"}) + public void lastModifiedOnlyDate() throws Exception { + final List responseHeaders = new ArrayList<>(); + responseHeaders.clear(); + responseHeaders.add(new NameValuePair("Date", "Fri, 16 Oct 2009 13:59:47 GMT")); + + expandExpectedAlertsVariables(DateUtils.formatDate(new Date()).substring(0, 17)); + final String html = "\n" + + "\n" + + ""; + + getMockWebConnection().setResponse(URL_FIRST, html, 200, "OK", MimeType.TEXT_HTML, responseHeaders); + + final WebDriver driver = loadPage2(URL_FIRST, ISO_8859_1); + verifyTitle2(driver, getExpectedAlerts()); + + // for some strange reasons, the selenium driven browser is in an invalid + // state after this test + releaseResources(); + shutDownAll(); + } + + private void testLastModified(final List responseHeaders, final String tz) throws Exception { + final String html = "\n" + + "\n" + + ""; + + shutDownAll(); + try { + getMockWebConnection().setResponse(URL_FIRST, html, 200, "OK", MimeType.TEXT_HTML, responseHeaders); + + final BrowserVersion.BrowserVersionBuilder builder + = new BrowserVersion.BrowserVersionBuilder(getBrowserVersion()); + builder.setSystemTimezone(TimeZone.getTimeZone(tz)); + setBrowserVersion(builder.build()); + + final WebDriver driver = loadPage2(URL_FIRST, ISO_8859_1); + verifyTitle2(driver, getExpectedAlerts()); + } + finally { + shutDownAll(); + } + } + + /** + * If neither Date header nor Last-Modified header is present, current time is taken. + * @throws Exception if the test fails + */ + @Test + @Alerts({"true", "true"}) + public void lastModified_noDateHeader() throws Exception { + final String html = "\n" + + "\n" + + ""; + + loadPageVerifyTitle2(html); + } + + /** + * Regression test for bug 2919853 (format of document.lastModified was incorrect). + * @throws Exception if an error occurs + */ + @Test + public void lastModified_format() throws Exception { + final String html + = "\n" + + ""; + + final WebDriver driver = loadPageWithAlerts2(html); + final String lastModified = driver.findElement(By.id("i")).getAttribute("value"); + + try { + new SimpleDateFormat("MM/dd/yyyy HH:mm:ss", Locale.ROOT).parse(lastModified); + } + catch (final ParseException e) { + fail(e.getMessage()); + } + } } diff --git a/src/test/java/org/htmlunit/javascript/host/html/HTMLElementTest.java b/src/test/java/org/htmlunit/javascript/host/html/HTMLElementTest.java index 62ee75679f1..531bc7727bf 100644 --- a/src/test/java/org/htmlunit/javascript/host/html/HTMLElementTest.java +++ b/src/test/java/org/htmlunit/javascript/host/html/HTMLElementTest.java @@ -5442,6 +5442,175 @@ public void hidden() throws Exception { loadPageVerifyTitle2(html); } + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts(DEFAULT = {"1 null/false", "2 /true", "3 /true", "4 hidden/true", "5 true/true", "6 false/true", + "7 until-found/until-found", "8 show/true", "9 Until-Found/true", "10 HIDDEN/true"}, + FF = {"1 null/false", "2 /true", "3 /true", "4 hidden/true", "5 true/true", "6 false/true", + "7 until-found/true", "8 show/true", "9 Until-Found/true", "10 HIDDEN/true"}, + FF_ESR = {"1 null/false", "2 /true", "3 /true", "4 hidden/true", "5 true/true", "6 false/true", + "7 until-found/true", "8 show/true", "9 Until-Found/true", "10 HIDDEN/true"}) + @HtmlUnitNYI(CHROME = {"1 null/false", "2 /true", "3 /true", "4 hidden/true", "5 true/true", "6 false/true", + "7 until-found/true", "8 show/true", "9 Until-Found/true", "10 HIDDEN/true"}, + EDGE = {"1 null/false", "2 /true", "3 /true", "4 hidden/true", "5 true/true", "6 false/true", + "7 until-found/true", "8 show/true", "9 Until-Found/true", "10 HIDDEN/true"}) + public void hiddenGet() throws Exception { + final String html + = "\n" + + "

    p1

    \n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + "\n" + + + "\n" + + "\n" + + + "\n" + + ""; + + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts(DEFAULT = {"1 null/false", "2 null/false", "3 /true", "4 /true", "5 null/false", + "6 null/false", "7 /true", "8 /true", + "9 null/false", "10 /true", "11 /true", + "12 null/false", "13 until-found/until-found", + "14 null/false", "15 until-found/until-found", + "16 null/false", "17 /true"}, + FF = {"1 null/false", "2 null/false", "3 /true", "4 /true", "5 null/false", + "6 null/false", "7 /true", "8 /true", + "9 null/false", "10 /true", "11 /true", + "12 null/false", "13 /true", + "14 null/false", "15 /true", + "16 null/false", "17 /true"}, + FF_ESR = {"1 null/false", "2 null/false", "3 /true", "4 /true", "5 null/false", + "6 null/false", "7 /true", "8 /true", + "9 null/false", "10 /true", "11 /true", + "12 null/false", "13 /true", + "14 null/false", "15 /true", + "16 null/false", "17 /true"}) + @HtmlUnitNYI(CHROME = {"1 null/false", "2 null/false", "3 /true", "4 /true", "5 null/false", + "6 null/false", "7 /true", "8 /true", + "9 null/false", "10 /true", "11 /true", + "12 null/false", "13 /true", + "14 null/false", "15 /true", + "16 null/false", "17 /true"}, + EDGE = {"1 null/false", "2 null/false", "3 /true", "4 /true", "5 null/false", + "6 null/false", "7 /true", "8 /true", + "9 null/false", "10 /true", "11 /true", + "12 null/false", "13 /true", + "14 null/false", "15 /true", + "16 null/false", "17 /true"}) + public void hiddenSet() throws Exception { + final String html + = "\n" + + "

    p1

    \n" + + "

    p2

    \n" + + "

    p3

    \n" + + "

    p4

    \n" + + "

    p5

    \n" + + "

    p6

    \n" + + + "\n" + + ""; + + loadPageVerifyTitle2(html); + } + /** * @throws Exception if the test fails */ diff --git a/src/test/java/org/htmlunit/javascript/host/html/HTMLImageElement2Test.java b/src/test/java/org/htmlunit/javascript/host/html/HTMLImageElement2Test.java index 7e1015fdc03..010b88f7c76 100644 --- a/src/test/java/org/htmlunit/javascript/host/html/HTMLImageElement2Test.java +++ b/src/test/java/org/htmlunit/javascript/host/html/HTMLImageElement2Test.java @@ -105,6 +105,7 @@ public void onload_complex_JavascriptDisabled() throws Exception { final HtmlPage page = loadPage(html); page.getElementById("myId").click(); assertEquals(getExpectedAlerts(), collectedAlerts); + assertEquals(1, getMockWebConnection().getRequestCount()); assertEquals(URL_FIRST, getMockWebConnection().getLastWebRequest().getUrl()); } @@ -145,17 +146,14 @@ public void onload_complex_JavascriptEngineDisabled() throws Exception { try (WebClient webClient = new WebClient(getBrowserVersion(), false, null, -1)) { final List collectedAlerts = new ArrayList<>(); - webClient.setAlertHandler(new CollectingAlertHandler(collectedAlerts)); - final MockWebConnection webConnection = getMockWebConnection(); - webConnection.setResponse(URL_FIRST, html); + final HtmlPage page = loadPage(webClient, html, collectedAlerts); + assertFalse(page.getWebClient().isJavaScriptEngineEnabled()); - webClient.setWebConnection(webConnection); - - final HtmlPage page = loadPage(html); page.getElementById("myId").click(); assertEquals(getExpectedAlerts(), collectedAlerts); - assertEquals(URL_SECOND, webConnection.getLastWebRequest().getUrl()); + assertEquals(1, getMockWebConnection().getRequestCount()); + assertEquals(URL_FIRST, getMockWebConnection().getLastWebRequest().getUrl()); } } diff --git a/src/test/java/org/htmlunit/javascript/host/html/HTMLScriptElementTest.java b/src/test/java/org/htmlunit/javascript/host/html/HTMLScriptElementTest.java index bc294b33032..e50f50f6a00 100644 --- a/src/test/java/org/htmlunit/javascript/host/html/HTMLScriptElementTest.java +++ b/src/test/java/org/htmlunit/javascript/host/html/HTMLScriptElementTest.java @@ -1578,4 +1578,91 @@ public void onErrorHandler() throws Exception { loadPageVerifyTitle2(html); } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"var x = 'HtmlUnit'", " htmx rocks!"}) + public void innerHtml1() throws Exception { + final String html = + "\n" + + " \n" + + " Page Title\n" + + " \n" + + " \n" + + " " + + " \n" + + LOG_TEXTAREA + + " \n" + + ""; + + loadPageVerifyTextArea2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"var x = 'HtmlUnit'", "
    htmx rocks
    "}) + public void innerHtmlTag() throws Exception { + final String html = + "\n" + + " \n" + + " Page Title\n" + + " \n" + + " \n" + + " \n" + + " \n" + + LOG_TEXTAREA + + " \n" + + ""; + + loadPageVerifyTextArea2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"", "</> htmx rocks!"}) + public void innerHtmlEscaping() throws Exception { + final String html = + "\n" + + " \n" + + " Page Title\n" + + " \n" + + " \n" + + " \n" + + " \n" + + LOG_TEXTAREA + + " \n" + + ""; + + loadPageVerifyTextArea2(html); + } } diff --git a/src/test/java/org/htmlunit/javascript/host/html/HTMLStyleElementTest.java b/src/test/java/org/htmlunit/javascript/host/html/HTMLStyleElementTest.java index 25e035bb88e..dc0de2a58a0 100644 --- a/src/test/java/org/htmlunit/javascript/host/html/HTMLStyleElementTest.java +++ b/src/test/java/org/htmlunit/javascript/host/html/HTMLStyleElementTest.java @@ -466,4 +466,88 @@ public void scriptInCdataHtml() throws Exception { } loadPageVerifyTitle2(html); } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"#id { color: red }", ":before { content: \" HtmlUnit\" }"}) + public void innerHtml1() throws Exception { + final String html = + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + LOG_TEXTAREA + + " \n" + + ""; + + loadPageVerifyTextArea2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"#id { color: red }", ":before { content: \"HtmlUnit\" }"}) + public void innerHtmlTag() throws Exception { + final String html = + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + LOG_TEXTAREA + + " \n" + + ""; + + loadPageVerifyTextArea2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"", ":before { content: \"</> HtmlUnit\" }"}) + public void innerHtmlEscaping() throws Exception { + final String html = + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + LOG_TEXTAREA + + " \n" + + ""; + + loadPageVerifyTextArea2(html); + } } diff --git a/src/test/java/org/htmlunit/javascript/host/html/HTMLTextAreaElementTest.java b/src/test/java/org/htmlunit/javascript/host/html/HTMLTextAreaElementTest.java index 313579014db..a12607afe83 100644 --- a/src/test/java/org/htmlunit/javascript/host/html/HTMLTextAreaElementTest.java +++ b/src/test/java/org/htmlunit/javascript/host/html/HTMLTextAreaElementTest.java @@ -790,4 +790,91 @@ private void mouseOver(final String element) throws Exception { assertTitle(driver, getExpectedAlerts()[0]); } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"HtmlUnit", " htmx rocks!"}) + public void innerHtml() throws Exception { + final String html = + "\n" + + " \n" + + " Page Title\n" + + " \n" + + " \n" + + " " + + " \n" + + LOG_TEXTAREA + + " \n" + + ""; + + loadPageVerifyTextArea2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"HtmlUnit", "
    htmx rocks
    "}) + public void innerHtmlTag() throws Exception { + final String html = + "\n" + + " \n" + + " Page Title\n" + + " \n" + + " \n" + + " \n" + + " \n" + + LOG_TEXTAREA + + " \n" + + ""; + + loadPageVerifyTextArea2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"", " htmx rocks!"}) + public void innerHtmlEscaping() throws Exception { + final String html = + "\n" + + " \n" + + " Page Title\n" + + " \n" + + " \n" + + " \n" + + " \n" + + LOG_TEXTAREA + + " \n" + + ""; + + loadPageVerifyTextArea2(html); + } } diff --git a/src/test/java/org/htmlunit/javascript/host/html/HTMLTitleElementTest.java b/src/test/java/org/htmlunit/javascript/host/html/HTMLTitleElementTest.java index 3fc8f7c2567..bbeaa0120b1 100644 --- a/src/test/java/org/htmlunit/javascript/host/html/HTMLTitleElementTest.java +++ b/src/test/java/org/htmlunit/javascript/host/html/HTMLTitleElementTest.java @@ -82,4 +82,91 @@ public void textCreateElement() throws Exception { loadPageVerifyTextArea2(html); } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"Page Title", " htmx rocks!", " htmx rocks!"}) + public void innerHtml() throws Exception { + final String html = + "\n" + + " \n" + + " Page Title\n" + + " \n" + + " \n" + + " \n" + + LOG_TEXTAREA + + " \n" + + ""; + + loadPageVerifyTextArea2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"Page Title", "
    htmx rocks
    ", "
    htmx rocks
    "}) + public void innerHtmlTag() throws Exception { + final String html = + "\n" + + " \n" + + " Page Title\n" + + " \n" + + " \n" + + " \n" + + LOG_TEXTAREA + + " \n" + + ""; + + loadPageVerifyTextArea2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts({"", " htmx rocks!", " htmx rocks!"}) + public void innerHtmlEscaping() throws Exception { + final String html = + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + LOG_TEXTAREA + + " \n" + + ""; + + loadPageVerifyTextArea2(html); + } } diff --git a/src/test/java/org/htmlunit/javascript/host/intl/DateTimeFormat2Test.java b/src/test/java/org/htmlunit/javascript/host/intl/DateTimeFormat2Test.java index e461ee1eae6..5a85ab60975 100644 --- a/src/test/java/org/htmlunit/javascript/host/intl/DateTimeFormat2Test.java +++ b/src/test/java/org/htmlunit/javascript/host/intl/DateTimeFormat2Test.java @@ -44,7 +44,7 @@ private void test(final String... string) throws Exception { + "\n" + + "\n" + + "\n" + + ""; + + shutDownAll(); + try { + final BrowserVersion.BrowserVersionBuilder builder + = new BrowserVersion.BrowserVersionBuilder(getBrowserVersion()); + builder.setSystemTimezone(TimeZone.getTimeZone(tz)); + setBrowserVersion(builder.build()); + + loadPageVerifyTitle2(html); + } + finally { + shutDownAll(); + } + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts("America/New_York") + @BuggyWebDriver(FF = "Europe/Berlin", FF_ESR = "Europe/Berlin") + public void timeZone() throws Exception { + final String html + = "\n" + + ""; + + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "+00:00", + FF = "GMT", + FF_ESR = "GMT") + @BuggyWebDriver(FF = "Europe/Berlin", FF_ESR = "Europe/Berlin") + @HtmlUnitNYI(CHROME = "GMT", EDGE = "GMT") + public void timeZoneGMT() throws Exception { + timeZone("GMT"); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts("UTC") + @BuggyWebDriver(FF = "Europe/Berlin", FF_ESR = "Europe/Berlin") + public void timeZoneUTC() throws Exception { + timeZone("UTC"); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "Etc/GMT+5", + FF = "EST", + FF_ESR = "EST") + @BuggyWebDriver(FF = "Europe/Berlin", FF_ESR = "Europe/Berlin") + @HtmlUnitNYI(CHROME = "EST", EDGE = "EST") + public void timeZoneEST() throws Exception { + timeZone("EST"); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts("Europe/Berlin") + public void timeZoneBerlin() throws Exception { + timeZone("Europe/Berlin"); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts("America/New_York") + @BuggyWebDriver(FF = "Europe/Berlin", FF_ESR = "Europe/Berlin") + public void timeZoneNewYork() throws Exception { + timeZone("America/New_York"); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts("Asia/Tokyo") + @BuggyWebDriver(FF = "Europe/Berlin", FF_ESR = "Europe/Berlin") + public void timeZoneTokyo() throws Exception { + timeZone("Asia/Tokyo"); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "Asia/Tokyo", + FF = "JST", + FF_ESR = "JST") + @BuggyWebDriver(FF = "Europe/Berlin", FF_ESR = "Europe/Berlin") + @HtmlUnitNYI(CHROME = "JST", EDGE = "JST") + public void timeZoneJST() throws Exception { + timeZone("JST"); + } + + private void timeZone(final String tz) throws Exception { + final String html + = "\n" + + ""; + + shutDownAll(); + try { + final BrowserVersion.BrowserVersionBuilder builder + = new BrowserVersion.BrowserVersionBuilder(getBrowserVersion()); + builder.setSystemTimezone(TimeZone.getTimeZone(tz)); + setBrowserVersion(builder.build()); + + loadPageVerifyTitle2(html); + } + finally { + shutDownAll(); + } + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts("en-US") + public void locale() throws Exception { + final String html + = "\n" + + ""; + + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "de", + EDGE = "de-DE") + @BuggyWebDriver(FF = "en-US", FF_ESR = "en-US") + @HtmlUnitNYI(CHROME = "de-DE", + FF = "de-DE", + FF_ESR = "de-DE") + public void localeGermany() throws Exception { + locale(Locale.GERMANY.toLanguageTag()); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "de", + EDGE = "de-DE") + @BuggyWebDriver(FF = "en-US", FF_ESR = "en-US") + @HtmlUnitNYI(EDGE = "de") + public void localeGerman() throws Exception { + locale(Locale.GERMAN.toLanguageTag()); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts("fr") + @BuggyWebDriver(FF = "en-US", FF_ESR = "en-US") + public void localeFrench() throws Exception { + locale(Locale.FRENCH.toLanguageTag()); + } + + /** + * @throws Exception if the test fails + */ + @Test + @Alerts("en-GB") + @BuggyWebDriver(FF = "en-US", FF_ESR = "en-US") + @HtmlUnitNYI(CHROME = "en-CA", + EDGE = "en-CA", + FF = "en-CA", + FF_ESR = "en-CA") + public void localeCanada() throws Exception { + locale(Locale.CANADA.toLanguageTag()); + } + + private void locale(final String language) throws Exception { + final String html + = "\n" + + ""; + + shutDownAll(); + try { + final BrowserVersion.BrowserVersionBuilder builder + = new BrowserVersion.BrowserVersionBuilder(getBrowserVersion()); + builder.setBrowserLanguage(language); + setBrowserVersion(builder.build()); + + loadPageVerifyTitle2(html); + } + finally { + shutDownAll(); + } + } } diff --git a/src/test/java/org/htmlunit/libraries/HtmxTest1x7x0.java b/src/test/java/org/htmlunit/libraries/HtmxTest1x7x0.java index 640ec318686..5424a791a6b 100644 --- a/src/test/java/org/htmlunit/libraries/HtmxTest1x7x0.java +++ b/src/test/java/org/htmlunit/libraries/HtmxTest1x7x0.java @@ -16,6 +16,7 @@ import org.htmlunit.junit.BrowserRunner; import org.htmlunit.junit.BrowserRunner.Alerts; +import org.htmlunit.junit.BrowserRunner.BuggyWebDriver; import org.junit.Test; import org.junit.runner.RunWith; @@ -32,6 +33,7 @@ public class HtmxTest1x7x0 extends HtmxTest { */ @Test @Alerts("passes:446failures:0") + @BuggyWebDriver(CHROME = "passes:446failures:1", EDGE = "passes:446failures:1") public void htmx() throws Exception { htmx("htmx-1.7.0"); } diff --git a/src/test/java/org/htmlunit/libraries/HtmxTest1x8x4.java b/src/test/java/org/htmlunit/libraries/HtmxTest1x8x4.java index 651b1c70834..8b7674df0e5 100644 --- a/src/test/java/org/htmlunit/libraries/HtmxTest1x8x4.java +++ b/src/test/java/org/htmlunit/libraries/HtmxTest1x8x4.java @@ -16,6 +16,7 @@ import org.htmlunit.junit.BrowserRunner; import org.htmlunit.junit.BrowserRunner.Alerts; +import org.htmlunit.junit.BrowserRunner.BuggyWebDriver; import org.junit.Test; import org.junit.runner.RunWith; @@ -32,6 +33,7 @@ public class HtmxTest1x8x4 extends HtmxTest { */ @Test @Alerts("passes:483failures:0") + @BuggyWebDriver(CHROME = "passes:483failures:1", EDGE = "passes:483failures:1") public void htmx() throws Exception { htmx("htmx-1.8.4"); } diff --git a/src/test/java/org/htmlunit/libraries/HtmxTest1x9x10.java b/src/test/java/org/htmlunit/libraries/HtmxTest1x9x10.java index 0285d7f79c3..acb715e5d86 100644 --- a/src/test/java/org/htmlunit/libraries/HtmxTest1x9x10.java +++ b/src/test/java/org/htmlunit/libraries/HtmxTest1x9x10.java @@ -18,7 +18,7 @@ import org.htmlunit.javascript.preprocessor.HtmxOneNineTenScriptPreProcessor; import org.htmlunit.junit.BrowserRunner; import org.htmlunit.junit.BrowserRunner.Alerts; -import org.htmlunit.junit.BrowserRunner.HtmlUnitNYI; +import org.htmlunit.junit.BrowserRunner.BuggyWebDriver; import org.junit.Test; import org.junit.runner.RunWith; @@ -34,12 +34,8 @@ public class HtmxTest1x9x10 extends HtmxTest { * @throws Exception if an error occurs */ @Test - @Alerts(DEFAULT = "passes:679failures:1", - FF = "passes:679failures:0", - FF_ESR = "passes:679failures:0") - @HtmlUnitNYI( - CHROME = "passes:679failures:0", - EDGE = "passes:679failures:0") + @Alerts("passes:679failures:0") + @BuggyWebDriver(CHROME = "passes:679failures:1", EDGE = "passes:679failures:1") public void htmx() throws Exception { htmx("htmx-1.9.10"); } diff --git a/src/test/java/org/htmlunit/libraries/HtmxTest1x9x11.java b/src/test/java/org/htmlunit/libraries/HtmxTest1x9x11.java deleted file mode 100644 index 7c9cdb9e1d4..00000000000 --- a/src/test/java/org/htmlunit/libraries/HtmxTest1x9x11.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2002-2024 Gargoyle Software Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.htmlunit.libraries; - -import org.htmlunit.WebClient; -import org.htmlunit.javascript.preprocessor.HtmxOneNineTenScriptPreProcessor; -import org.htmlunit.junit.BrowserRunner; -import org.htmlunit.junit.BrowserRunner.Alerts; -import org.htmlunit.junit.BrowserRunner.HtmlUnitNYI; -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Tests for htmx. - * - * @author Ronald Brill - */ -@RunWith(BrowserRunner.class) -public class HtmxTest1x9x11 extends HtmxTest { - - /** - * @throws Exception if an error occurs - */ - @Test - @Alerts(DEFAULT = "passes:707failures:1", - FF = "passes:707failures:0", - FF_ESR = "passes:707failures:0") - @HtmlUnitNYI( - CHROME = "passes:707failures:0", - EDGE = "passes:707failures:0") - public void htmx() throws Exception { - htmx("htmx-1.9.11"); - } - - @Override - protected void setupWebClient(final WebClient webClient) { - super.setupWebClient(webClient); - - webClient.setScriptPreProcessor(new HtmxOneNineTenScriptPreProcessor()); - } -} diff --git a/src/test/java/org/htmlunit/libraries/HtmxTest1x9x12.java b/src/test/java/org/htmlunit/libraries/HtmxTest1x9x12.java index e55af4550a9..df47567a622 100644 --- a/src/test/java/org/htmlunit/libraries/HtmxTest1x9x12.java +++ b/src/test/java/org/htmlunit/libraries/HtmxTest1x9x12.java @@ -18,7 +18,7 @@ import org.htmlunit.javascript.preprocessor.HtmxOneNineTenScriptPreProcessor; import org.htmlunit.junit.BrowserRunner; import org.htmlunit.junit.BrowserRunner.Alerts; -import org.htmlunit.junit.BrowserRunner.HtmlUnitNYI; +import org.htmlunit.junit.BrowserRunner.BuggyWebDriver; import org.junit.Test; import org.junit.runner.RunWith; @@ -34,12 +34,8 @@ public class HtmxTest1x9x12 extends HtmxTest { * @throws Exception if an error occurs */ @Test - @Alerts(DEFAULT = "passes:707failures:1", - FF = "passes:707failures:0", - FF_ESR = "passes:707failures:0") - @HtmlUnitNYI( - CHROME = "passes:707failures:0", - EDGE = "passes:707failures:0") + @Alerts("passes:707failures:0") + @BuggyWebDriver(CHROME = "passes:707failures:1", EDGE = "passes:707failures:1") public void htmx() throws Exception { htmx("htmx-1.9.12"); } diff --git a/src/test/java/org/htmlunit/libraries/HtmxTest1x9x2.java b/src/test/java/org/htmlunit/libraries/HtmxTest1x9x2.java index 121203424a4..4c8d40f351c 100644 --- a/src/test/java/org/htmlunit/libraries/HtmxTest1x9x2.java +++ b/src/test/java/org/htmlunit/libraries/HtmxTest1x9x2.java @@ -16,6 +16,7 @@ import org.htmlunit.junit.BrowserRunner; import org.htmlunit.junit.BrowserRunner.Alerts; +import org.htmlunit.junit.BrowserRunner.BuggyWebDriver; import org.junit.Test; import org.junit.runner.RunWith; @@ -32,6 +33,7 @@ public class HtmxTest1x9x2 extends HtmxTest { */ @Test @Alerts("passes:529failures:0") + @BuggyWebDriver(CHROME = "passes:529failures:1", EDGE = "passes:529failures:1") public void htmx() throws Exception { htmx("htmx-1.9.2"); } diff --git a/src/test/java/org/htmlunit/libraries/HtmxTest1x9x6.java b/src/test/java/org/htmlunit/libraries/HtmxTest1x9x6.java deleted file mode 100644 index 0ff7df6351c..00000000000 --- a/src/test/java/org/htmlunit/libraries/HtmxTest1x9x6.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2002-2024 Gargoyle Software Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.htmlunit.libraries; - -import org.htmlunit.junit.BrowserRunner; -import org.htmlunit.junit.BrowserRunner.Alerts; -import org.htmlunit.junit.BrowserRunner.HtmlUnitNYI; -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Tests for htmx. - * - * @author Ronald Brill - */ -@RunWith(BrowserRunner.class) -public class HtmxTest1x9x6 extends HtmxTest { - - /** - * @throws Exception if an error occurs - */ - @Test - @Alerts(DEFAULT = "passes:634failures:1", - FF = "passes:634failures:0", - FF_ESR = "passes:634failures:0") - @HtmlUnitNYI( - CHROME = "passes:634failures:0", - EDGE = "passes:634failures:0") - public void htmx() throws Exception { - htmx("htmx-1.9.6"); - } -} diff --git a/src/test/java/org/htmlunit/libraries/HtmxTest1x9x7.java b/src/test/java/org/htmlunit/libraries/HtmxTest1x9x7.java deleted file mode 100644 index 1ef4e0c3ff2..00000000000 --- a/src/test/java/org/htmlunit/libraries/HtmxTest1x9x7.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2002-2024 Gargoyle Software Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.htmlunit.libraries; - -import org.htmlunit.junit.BrowserRunner; -import org.htmlunit.junit.BrowserRunner.Alerts; -import org.htmlunit.junit.BrowserRunner.HtmlUnitNYI; -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Tests for htmx. - * - * @author Ronald Brill - */ -@RunWith(BrowserRunner.class) -public class HtmxTest1x9x7 extends HtmxTest { - - /** - * @throws Exception if an error occurs - */ - @Test - @Alerts(DEFAULT = "passes:653failures:1", - FF = "passes:653failures:0", - FF_ESR = "passes:653failures:0") - @HtmlUnitNYI( - CHROME = "passes:653failures:0", - EDGE = "passes:653failures:0") - public void htmx() throws Exception { - htmx("htmx-1.9.7"); - } -} diff --git a/src/test/java/org/htmlunit/libraries/HtmxTest1x9x9.java b/src/test/java/org/htmlunit/libraries/HtmxTest1x9x9.java deleted file mode 100644 index 0230c6e754e..00000000000 --- a/src/test/java/org/htmlunit/libraries/HtmxTest1x9x9.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2002-2024 Gargoyle Software Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.htmlunit.libraries; - -import org.htmlunit.junit.BrowserRunner; -import org.htmlunit.junit.BrowserRunner.Alerts; -import org.htmlunit.junit.BrowserRunner.HtmlUnitNYI; -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Tests for htmx. - * - * @author Ronald Brill - */ -@RunWith(BrowserRunner.class) -public class HtmxTest1x9x9 extends HtmxTest { - - /** - * @throws Exception if an error occurs - */ - @Test - @Alerts(DEFAULT = "passes:668failures:1", - FF = "passes:668failures:0", - FF_ESR = "passes:668failures:0") - @HtmlUnitNYI( - CHROME = "passes:668failures:0", - EDGE = "passes:668failures:0") - public void htmx() throws Exception { - htmx("htmx-1.9.9"); - } -} diff --git a/src/test/java/org/htmlunit/libraries/Sarissa0997Test.java b/src/test/java/org/htmlunit/libraries/Sarissa0997Test.java new file mode 100644 index 00000000000..588a15e1aa9 --- /dev/null +++ b/src/test/java/org/htmlunit/libraries/Sarissa0997Test.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002-2024 Gargoyle Software Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.htmlunit.libraries; + +import org.htmlunit.WebDriverTestCase; +import org.htmlunit.junit.BrowserRunner; +import org.htmlunit.junit.BrowserRunner.Alerts; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; + +/** + * Tests for 0.9.9.3 version of Sarissa. + * + * @author Ahmed Ashour + * @author Marc Guillemot + * @author Frank Danek + * @author Ronald Brill + */ +@RunWith(BrowserRunner.class) +public class Sarissa0997Test extends WebDriverTestCase { + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts({"++++++++++++++++++", "+", "+", "+", "+++", "++", "++++++++"}) + public void sarissa() throws Exception { + startWebServer("src/test/resources/libraries/sarissa/0.9.9.7", null, null); + final String url = URL_FIRST + "test/testsarissa.html"; + + final WebDriver driver = getWebDriver(); + driver.get(url); + + driver.switchTo().alert().dismiss(); + + verify(driver, "SarissaTestCase", getExpectedAlerts()[0]); + verify(driver, "XmlHttpRequestTestCase", getExpectedAlerts()[1]); + verify(driver, "XMLSerializerTestCase", getExpectedAlerts()[2]); + verify(driver, "DOMParserTestCase", getExpectedAlerts()[3]); + verify(driver, "XMLDocumentTestCase", getExpectedAlerts()[4]); + verify(driver, "XMLElementTestCase", getExpectedAlerts()[5]); + verify(driver, "XSLTProcessorTestCase", getExpectedAlerts()[6]); + } + + /** + * @param expectedResult empty for successful test or in the form of "+++F+++" + * for failing tests (see the results in a real browser) + */ + private static void verify(final WebDriver driver, final String testName, final String expectedResult) { + final WebElement div = + driver.findElement(By.xpath("//div[@class='placeholder' and a[@name='#" + testName + "']]")); + + String text = div.getText(); + text = text.substring(0, text.indexOf(String.valueOf(expectedResult.length()))).trim(); + assertEquals(testName + " Results\n" + expectedResult, text); + } +} diff --git a/src/test/resources/libraries/MochiKit/1.4.1/test-Style.IE.expected.txt b/src/test/resources/libraries/MochiKit/1.4.1/test-Style.IE.expected.txt deleted file mode 100644 index f2207c027f4..00000000000 --- a/src/test/resources/libraries/MochiKit/1.4.1/test-Style.IE.expected.txt +++ /dev/null @@ -1,61 +0,0 @@ -Passed: 59 -Failed: 6 -ok - initial x position -ok - initial y position -ok - x position with offsetParent border -ok - y position with offsetParent border -ok - updated x position -ok - updated y position -ok - updated x position (using relativeTo parameter) -ok - updated y position (using relativeTo parameter) -ok - passthrough x position -ok - passthrough y position -ok - passthrough x position (using relativeTo parameter) -ok - passthrough y position (using relativeTo parameter) -ok - invalid element should return an undefined position -ok - updated only x position -ok - not updated y position -ok - test getStyle selector case -ok - test getStyle camel case -ok - test computed getStyle selector case -ok - test computed getStyle camel case -ok - test getStyle opacity -ok - test getOpacity -ok - test setOpacity -ok - test setOpacity -ok - test setOpacity -ok - getStyle of float -ok - getStyle of cssFloat -ok - getStyle of styleFloat -ok - getStyle of float when unset -ok - setStyle of CSS float -ok - setStyle of CSS cssFloat -ok - setStyle of CSS styleFloat -ok - getElementDimensions w ok -ok - getElementDimensions h ok -ok - getElementDimensions content w ok -ok - getElementDimensions content h ok -ok - setElementDimensions w ok -ok - setElementDimensions h ok -ok - setElementDimensions only w ok -ok - setElementDimensions h not updated ok -ok - getElementDimensions w ok when display none -ok - getElementDimensions h ok when display none -ok - getElementDimensions w ok when CSS display none -ok - getElementDimensions h ok when CSS display none -ok - getElementDimensions modified element display -ok - test getViewportDimensions w -ok - test getViewportDimensions h -ok - test getViewportPosition x -ok - test getViewportPosition y -ok - default left table cell content w ok -ok - default middle table cell content w ok -ok - default right table cell content w ok -ok - collapsed left table cell content w ok -ok - collapsed middle table cell content w ok -ok - collapsed right table cell content w ok -ok - make clipping on overflow-x -ok - make clipping on overflow-y -ok - undo clipping on overflow-x -ok - undo clipping on overflow-y -ok - test suite finished! \ No newline at end of file diff --git a/src/test/resources/libraries/MochiKit/1.4.1/test-Style.IE_NYI.expected.txt b/src/test/resources/libraries/MochiKit/1.4.1/test-Style.IE_NYI.expected.txt deleted file mode 100644 index 1f9d795206f..00000000000 --- a/src/test/resources/libraries/MochiKit/1.4.1/test-Style.IE_NYI.expected.txt +++ /dev/null @@ -1,59 +0,0 @@ -Passed: 57 -Failed: 8 -ok - initial x position -ok - initial y position -ok - x position with offsetParent border -ok - y position with offsetParent border -ok - updated x position -ok - updated y position -ok - updated x position (using relativeTo parameter) -ok - updated y position (using relativeTo parameter) -ok - passthrough x position -ok - passthrough y position -ok - passthrough x position (using relativeTo parameter) -ok - passthrough y position (using relativeTo parameter) -ok - invalid element should return an undefined position -ok - updated only x position -ok - not updated y position -ok - test getStyle selector case -ok - test getStyle camel case -ok - test computed getStyle selector case -ok - test computed getStyle camel case -ok - test getStyle opacity -ok - test getOpacity -ok - test setOpacity -ok - test setOpacity -ok - test setOpacity -ok - getStyle of float -ok - getStyle of cssFloat -ok - getStyle of styleFloat -ok - getStyle of float when unset -ok - setStyle of CSS float -ok - setStyle of CSS cssFloat -ok - setStyle of CSS styleFloat -ok - getElementDimensions w ok -ok - getElementDimensions h ok -ok - getElementDimensions content w ok -ok - getElementDimensions content h ok -ok - setElementDimensions w ok -ok - setElementDimensions h ok -ok - setElementDimensions only w ok -ok - setElementDimensions h not updated ok -ok - getElementDimensions w ok when display none -ok - getElementDimensions h ok when display none -ok - getElementDimensions w ok when CSS display none -ok - getElementDimensions h ok when CSS display none -ok - getElementDimensions modified element display -ok - test getViewportDimensions w -ok - test getViewportDimensions h -ok - test getViewportPosition x -ok - test getViewportPosition y -ok - default left table cell content w ok -ok - default middle table cell content w ok -ok - default right table cell content w ok -ok - collapsed middle table cell content w ok -ok - make clipping on overflow-x -ok - make clipping on overflow-y -ok - undo clipping on overflow-x -ok - undo clipping on overflow-y -ok - test suite finished! \ No newline at end of file diff --git a/src/test/resources/libraries/MochiKit/1.4.2/test-Style.IE.expected.txt b/src/test/resources/libraries/MochiKit/1.4.2/test-Style.IE.expected.txt deleted file mode 100644 index f2207c027f4..00000000000 --- a/src/test/resources/libraries/MochiKit/1.4.2/test-Style.IE.expected.txt +++ /dev/null @@ -1,61 +0,0 @@ -Passed: 59 -Failed: 6 -ok - initial x position -ok - initial y position -ok - x position with offsetParent border -ok - y position with offsetParent border -ok - updated x position -ok - updated y position -ok - updated x position (using relativeTo parameter) -ok - updated y position (using relativeTo parameter) -ok - passthrough x position -ok - passthrough y position -ok - passthrough x position (using relativeTo parameter) -ok - passthrough y position (using relativeTo parameter) -ok - invalid element should return an undefined position -ok - updated only x position -ok - not updated y position -ok - test getStyle selector case -ok - test getStyle camel case -ok - test computed getStyle selector case -ok - test computed getStyle camel case -ok - test getStyle opacity -ok - test getOpacity -ok - test setOpacity -ok - test setOpacity -ok - test setOpacity -ok - getStyle of float -ok - getStyle of cssFloat -ok - getStyle of styleFloat -ok - getStyle of float when unset -ok - setStyle of CSS float -ok - setStyle of CSS cssFloat -ok - setStyle of CSS styleFloat -ok - getElementDimensions w ok -ok - getElementDimensions h ok -ok - getElementDimensions content w ok -ok - getElementDimensions content h ok -ok - setElementDimensions w ok -ok - setElementDimensions h ok -ok - setElementDimensions only w ok -ok - setElementDimensions h not updated ok -ok - getElementDimensions w ok when display none -ok - getElementDimensions h ok when display none -ok - getElementDimensions w ok when CSS display none -ok - getElementDimensions h ok when CSS display none -ok - getElementDimensions modified element display -ok - test getViewportDimensions w -ok - test getViewportDimensions h -ok - test getViewportPosition x -ok - test getViewportPosition y -ok - default left table cell content w ok -ok - default middle table cell content w ok -ok - default right table cell content w ok -ok - collapsed left table cell content w ok -ok - collapsed middle table cell content w ok -ok - collapsed right table cell content w ok -ok - make clipping on overflow-x -ok - make clipping on overflow-y -ok - undo clipping on overflow-x -ok - undo clipping on overflow-y -ok - test suite finished! \ No newline at end of file diff --git a/src/test/resources/libraries/MochiKit/1.4.2/test-Style.IE_NYI.expected.txt b/src/test/resources/libraries/MochiKit/1.4.2/test-Style.IE_NYI.expected.txt deleted file mode 100644 index 1f9d795206f..00000000000 --- a/src/test/resources/libraries/MochiKit/1.4.2/test-Style.IE_NYI.expected.txt +++ /dev/null @@ -1,59 +0,0 @@ -Passed: 57 -Failed: 8 -ok - initial x position -ok - initial y position -ok - x position with offsetParent border -ok - y position with offsetParent border -ok - updated x position -ok - updated y position -ok - updated x position (using relativeTo parameter) -ok - updated y position (using relativeTo parameter) -ok - passthrough x position -ok - passthrough y position -ok - passthrough x position (using relativeTo parameter) -ok - passthrough y position (using relativeTo parameter) -ok - invalid element should return an undefined position -ok - updated only x position -ok - not updated y position -ok - test getStyle selector case -ok - test getStyle camel case -ok - test computed getStyle selector case -ok - test computed getStyle camel case -ok - test getStyle opacity -ok - test getOpacity -ok - test setOpacity -ok - test setOpacity -ok - test setOpacity -ok - getStyle of float -ok - getStyle of cssFloat -ok - getStyle of styleFloat -ok - getStyle of float when unset -ok - setStyle of CSS float -ok - setStyle of CSS cssFloat -ok - setStyle of CSS styleFloat -ok - getElementDimensions w ok -ok - getElementDimensions h ok -ok - getElementDimensions content w ok -ok - getElementDimensions content h ok -ok - setElementDimensions w ok -ok - setElementDimensions h ok -ok - setElementDimensions only w ok -ok - setElementDimensions h not updated ok -ok - getElementDimensions w ok when display none -ok - getElementDimensions h ok when display none -ok - getElementDimensions w ok when CSS display none -ok - getElementDimensions h ok when CSS display none -ok - getElementDimensions modified element display -ok - test getViewportDimensions w -ok - test getViewportDimensions h -ok - test getViewportPosition x -ok - test getViewportPosition y -ok - default left table cell content w ok -ok - default middle table cell content w ok -ok - default right table cell content w ok -ok - collapsed middle table cell content w ok -ok - make clipping on overflow-x -ok - make clipping on overflow-y -ok - undo clipping on overflow-x -ok - undo clipping on overflow-y -ok - test suite finished! \ No newline at end of file diff --git a/src/test/resources/libraries/chartjs/2.9.4/expectations/simple_bar_chart.Chrome.expected b/src/test/resources/libraries/chartjs/2.9.4/expectations/simple_bar_chart.Chrome.expected index 00b9f52943d..ce864077f8d 100644 --- a/src/test/resources/libraries/chartjs/2.9.4/expectations/simple_bar_chart.Chrome.expected +++ b/src/test/resources/libraries/chartjs/2.9.4/expectations/simple_bar_chart.Chrome.expected @@ -1 +1 @@ -data:image/png;base64,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 \ No newline at end of file +data:image/png;base64,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 \ No newline at end of file diff --git a/src/test/resources/libraries/chartjs/2.9.4/expectations/simple_bar_chart.Edge.expected b/src/test/resources/libraries/chartjs/2.9.4/expectations/simple_bar_chart.Edge.expected index 00b9f52943d..d1dcc2dcbc2 100644 --- a/src/test/resources/libraries/chartjs/2.9.4/expectations/simple_bar_chart.Edge.expected +++ b/src/test/resources/libraries/chartjs/2.9.4/expectations/simple_bar_chart.Edge.expected @@ -1 +1 @@ -data:image/png;base64,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 \ No newline at end of file +data:image/png;base64,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 \ No newline at end of file diff --git a/src/test/resources/libraries/chartjs/2.9.4/expectations/simple_bar_chart.FF-ESR.expected b/src/test/resources/libraries/chartjs/2.9.4/expectations/simple_bar_chart.FF-ESR.expected index 8c83cf85b92..25809ea18d5 100644 --- a/src/test/resources/libraries/chartjs/2.9.4/expectations/simple_bar_chart.FF-ESR.expected +++ b/src/test/resources/libraries/chartjs/2.9.4/expectations/simple_bar_chart.FF-ESR.expected @@ -1 +1 @@ -data:image/png;base64,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 \ No newline at end of file +data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAB2gAAAEsCAYAAAAGmePsAAAgAElEQVR4XuzdD5Ql1X0f+H7dIxiZGckeUPCMkDhBf9gVcqT1EMVowQOyIjmskVFQFB+02IFNujM6WttCOMSxAoNixbEPIB17o053dMC7ZIhXThYM8SIt8QokNlFkxhzpGJkBRCxGnokUgRbNgNZIPW9/1Xlv8rqn/7z3qurVrapPn1Nnut+run8+93Kpft+uqs6ULwIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBCYiEBnIrWohAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSmBLQmAQECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBCYkIKCdELRqCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgIKA1BwgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIDAhAQHthKBVQ4AAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQGtOUCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIEJCQhoJwStGgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECAhozQECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAhMSEBAOyFo1RAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQEBAaw4QIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBgQgIC2glBq4YAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQICWnOAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECExIQ0E4IWjUECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAQ0JoDBAgQIECAAAECBAgQSESgO/uPXjO11PlkIs2ZXDNmtvxcZ/HvPz25CtVEgAABAgQIECBAgAABAgSqExDQVmevZgIECBAgQIAAAQIECKwQ6P5PH/2Jqanuv53qTP3ZVLf7n5rPM70z+rtrqnP8xzufvOHzze+vHhIgQIAAAQIECBAgQIAAgan4td8XAQIECBAgQIAAAQIECCQhcCKgnTr+d+K3tUeSaFSZjehM/+Wp41Pzowa0c3NzD0ez/unCwsLtWfNmZ2fviX8OLC4u3lRE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 \ No newline at end of file diff --git a/src/test/resources/libraries/chartjs/2.9.4/expectations/simple_bar_chart.FF.expected b/src/test/resources/libraries/chartjs/2.9.4/expectations/simple_bar_chart.FF.expected index 8c83cf85b92..25809ea18d5 100644 --- a/src/test/resources/libraries/chartjs/2.9.4/expectations/simple_bar_chart.FF.expected +++ b/src/test/resources/libraries/chartjs/2.9.4/expectations/simple_bar_chart.FF.expected @@ -1 +1 @@ -data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABPQAAADICAYAAABvTr+qAAAeDElEQVR4nO3df4ik930f8Ke4RxvoXyk0xW36Ky0HvTR4T5Uit0tzdsFanx3V9CS5aiVVK1nfb1BRlUuKaVzQ6Jw7y+A6VcHnu0kalOgcERQIdKgkOCqFy/1TytpcKQiVa6F/NFNc/VeEoKXw9A8/c3r20ezufOaZm2e/u68XvPHuzuzs2Jl3ZuZ9z8xUFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUVVXVT/3qi4c9Q/9vBAAAAACHRv30xbp+6uL40Obpi/V+1z/nvJ1z3qmqqkopTVJKo8h//5TSZkqpTinVOeftzs8+dlkppelefyOlNJ5dFwAAAAC4K+qnL9b1V75+z6HNAYNeSmmUUhpXVVXlnHdmo9yiUkqjeSNcc1k7nZ9tp5T2vD4GPQAAAADuulIHvZTSeHZkXTd7nH/SOs+4+dmo9bNp5/yj7mU1lzFZ4LIme/3NqvpoGGxls9//FQEAAAA4Nkod9Gaal8Butl96O+c8d8a52ctpWy+vHXXHvNbv1e0j/mZj3T6XNW69/Hc8u9w555u2/76j+gAAAABY2BEY9Gbj2mh2ZFxXznmnfYTc7Ci71u/NHfSa39t1vgMu686g15xvtMf59nwfPgAAAADYV6mDXuQlt82AFh702qfNhrwDLqt9hN50znWbtH7PS24BAAAAiCt10KuqxT8QY9kj9FLr025nw9uyR+jt99/BS24BAAAAWFjhg95kNprt9WEYzWkfew+91u/tOehV1Z1hrm4debffZc19D73m+ztH9rWPyjPoAQAAABBS+KB34AditM479xNnDxr0Wi/t7b4f3p6fXtsa9drna7/ctv2JuPu+RyAAAAAA7FLyoAcAAAAAx45BDwAAAAAKUj99sa6fujg+tDHoAQAAAMBH6qd+9cXDnqH/NwIAAAAAAAAAAAAAAAAAAAAAOIxSStOUUp1SqnPOO+3Tcs7bs9NSSpOhriMAAAAAUFVVSmmSUhq3vp92vq9zztut00ZDXE8AAAAAYI5m4Js0X49SStPWaePuEXwAAAAAwIByzjuzI/S6A1534AMAAAAABpRSGqeU6vb3Bj0AAAAAOISasa5OKW22fmbQAwAAAIDDpntkXuvne72H3omqqj65QM4teD4R+Sgbh+A6iJQWvRGJR29E4tEbkXj0RmS57O+go+56fsrtucB5gR85uLhAl95AnN5AnN5AnN5A3EKD3rR5qe2dtF9mm3Pebp02CV4Bgx7EucODOL2BOL2BOL2BOL2BuMF7Y9CDuMGLCwXSG4jTG4jTG4jTG4gbvDcGPYgbvLhQIL2BOL2BOL2BOL2BuMF7Y9CDuMGLCwXSG4jTG4jTG4jTG4gbvDcGPYhbe3HP/EH9x//qm7f/hMgq8vDr9SfWfRuuDsEdHhRIbyBObyBObyBu8N4Y9CBu7cW955X/9fDPvvr+/xbpm/tefb++97ff/9a6b8PVIbjDgwLpDcTpDcTpDcTFepNz3kkpjds/SymNfcotrNUgg969r/5w/LO/9f49Ir3y6g9/2aAHxdAbiNMbiNMbiFu8N82YV7cHvZzzdvOzzaqqqubrUeAKGPQgzqAn5cagByXRG4jTG4jTG4hbrDezIS+lNG0PeimlUUppOvt+3hF8BzDoQZxBT8qNQQ9KojcQpzcQpzcQF+vNnEFv0xF6sHYGPSk3Bj0oid5AnN5AnN5AXL9Br/nZbNSrc87bwStg0IM4g56UG4MelERvIE5vIE5vIK73EXrjOS+5nVRVdaK58INybsHzichH2Vj33zx16WY6ffX2tZPnX9sS6ZONl29d2Lj83pXj0BuRIxC9EYlHb0Ti0RuR5bK4OYPepP3Jtt331FuAI/QgLlbcFXCEnqwsjtCDkugNxOkNxOkNxPUe9PY6Qm9RBj2IM+hJuTHoQUn0BuL0BuL0BuL6DXrNzyaz99ALHp1XVQY9WIZBT8qNQQ9KojcQpzcQpzcQN3hvDHoQZ9CTcmPQg5LoDcTpDcTpDcQN3huDHsQZ9KTcGPSgJHoDcXoDcXoDcYP3xqAHcQY9KTcGPSiJ3kCc3kCc3kDc4L0x6EGcQU/KjUEPSqI3EKc3EKc3EDd4bwx6EGfQk3Jj0IOS6A3E6Q3E6Q3ExXqTc97pfsptznm79Sm3dfAKGPQgzqAn5cagByXRG4jTG4jTG4hbvDfNmFd3B72UUp1z3m6+HqeUJoErYNCDOIOelBuDHpREbyBObyBObyBusd7MhryU0rQ96KWURsEBr8ugB3EGPSk3Bj0oid5AnN5AnN5AXKw3cwa9STP0zV5yOw1eAYMexBn0pNwY9KAkegNxegNxegNxKxn06pTSZlXdeVmul9zC3WXQk3Jj0IOS6A3E6Q3E6Q3ErWTQm7S+HzVH6Z1oLvygnFvwfCLyUTbW/TdPXbqZTl+9fe3k+de2RPpk4+VbFzYuv3flOPRG5AhEb0Ti0RuRePRGZLksbs6gN84577S+HwVfdusIPYiLFXcFHKEnK4sj9KAkegNxegNxegNxvQe9zfZLbrunL8CgB3EGPSk3Bj0oid5AnN5AnN5AXL9Br6qqKue8PftQjPbRegsy6EGcQU/KjUEPSqI3EKc3EKc3EDd4bwx6EGfQk3Jj0IOS6A3E6Q3E6Q3EDd4bgx7EGfSk3Bj0oCR6A3F6A3F6A3GD98agB3EGPSk3Bj0oid5AnN5AnN5A3OC9MehBnEFPyo1BD0qiNxCnNxCnNxA3eG8MehBn0JNyY9CDkugNxOkNxOkNxMV6k3Pe6X7K7UxKaZRSqoNXwKAHcQY9KTcGPSiJ3kCc3kCc3kDc4r1pxrx6n0GvNujBWhj0pNwY9KAkegNxegNxegNxi/VmNuSllKbzBr2U0mQ2+AWvgEEP4gx6Um4MelASvYE4vYE4vYG4WG/mDXo55+2U0rT5T4Me3H0GPSk3Bj0oid5AnN5AnN5AXP9BbzbmGfRgbQx6Um4MelASvYE4vYE4vYG4foNe8zLcSVXdOVJvNuidaC78oJxb8Hwi8lE21v03T126mU5fvX3t5PnXtkT6ZOPlWxc2Lr935Tj0RuQIRG9E4tEbkXj0RmS5LK476LU+KGNXAhfpCD2IixV3BRyhJyuLI/SgJHoDcXoDcXoDcf0GvTYvuYW1MehJuTHoQUn0BuL0BuL0BuIMelAgg56UG4MelERvIE5vIE5vIG7w3hj0IM6gJ+XGoAcl0RuI0xuI0xuIG7w3Bj2IM+hJuTHoQUn0BuL0BuL0BuIG741BD+IMelJuDHpQEr2BOL2BOL2BuMF7Y9CDOIOelBuDHpREbyBObyBObyBu8N4Y9CDOoCflxqAHJdEbiNMbiNMbiIv1Jue80/2U2+aTb+uUUp1z3gleAYMexBn0pNwY9KAkegNxegNxegNxi/emGfPq9qCXUpp0vp92B78DGPQgzqAn5cagByXRG4jTG4jTG4hbrDezIe+gwa4Z+CaBK2DQgziDnpQbgx6URG8gTm8gTm8gLtabgwa9eS/JPYBBD+IMelJuDHpQEr2BOL2BOL2BuNUNes0RfHXwChj0IM6gJ+XGoAcl0RuI0xuI0xuIW82gl1IaNS/L3Wx+dKK58INybsHzrSxvPPDY1of/+MV3RFaRP/qHX/3mum/DVVVtrPtvnrp0M52+evvayfOvbYn0ycbLty5sXH7vynHojcgRiN6IxKM3IvHojchyWdy8QW/JI/Nm1n6EXv30i/fVX7k4qb9y8VGRXnnqwov1UxffXPdtuIoWdwUcoScriyP0oCR6A3F6A3F6A3H9Br3myLxpjysw4KD39XtE+uXiowY9kWAMelASvYE4vYE4vYG43oPetHmp7Z3knHcCF2nQk4Jj0BMJx6AHJdEbiNMbiNMbiBu8NwY9KTgGPZFwDHpQEr2BOL2BOL2BuMF7Y9CTgmPQEwnHoAcl0RuI0xuI0xuIG7w3Bj0pOAY9kXAMelASvYE4vYE4vYG4wXtj0JOCY9ATCcegByXRG4jTG4jTG4iL9SbnvNP+UIzmZ9utD8WYBK+AQU8KjkFPJByDHpREbyBObyBObyBu8d40Y17dHfSaT7bdbr6eppRGgStg0JOCY9ATCcegByXRG4jTG4jTG4hbrDezIa8Z7Matn49SStPW9+Oc807gChj0pOAY9ETCMehBSfQG4vQG4vQG4mK9mTPo7RrwugPfAgx6UnAMeiLhGPSgJHoDcXoDcXoDcQY9keVj0BMJx6AHJdEbiNMbiNMbiLtrg96J5sIPyrkFz7eyXN96/OwHT75w/Y0HHtsS6ZN3H3r+2Q+fGL297ttwVVUb6/6bpy7dTKev3r528vxrWyJ9svHyrQsbl9+7chx6I3IEojci8eiNSDx6I7JcFuc99ETacYSeSDiO0IOS6A3E6Q3E6Q3E9Rv0mp/5lFs5pjHoiYRj0IOS6A3E6Q3E6Q3E9R/0cs7bzafg1imlSfAKGPSk4Bj0RMIx6EFJ9Abi9Abi9AbiBu+NQU8KjkFPJByDHpREbyBObyBObyBu8N4Y9KTgGPREwjHoQUn0BuL0BuL0BuIG741BTwqOQU8kHIMelERvIE5vIE5vIG7w3hj0pOAY9ETCMehBSfQG4vQG4vQG4gbvjUFPCo5BTyQcgx6URG8gTm8gTm8grn9vUkpjn3IrxzMGPZFwDHpQEr2BOL2BOL2BuH69yTlvN0PeZlVVVfP1KHARBj0pOAY9kXAMelASvYE4vYE4vYG4fr1JKY1SStPZ9znnnZTSOHARBj0pOAY9kXAMelASvYE4vYE4vYG43oPepiP05PjGoCcSjkEPSqI3EKc3EKc3ELeS99CbjXp1znk7+OsGPSk4Bj2RcAx6UBK9gTi9gTi9gbjeR+iN57zkdlJV1Ynmwg/KuQXPt7Jc33r87AdPvnD9jQce2xLpk3cfev7ZD58Yvb3u23BVVRvr/punLt1Mp6/evnby/GtbIn2y8fKtCxuX37tyHHojcgSiNyLx6I1IPHojslyWl1KatD/ZtvueegtwhJ4UHEfoiYTjCD0oid5AnN5AnN5AXO9Bb68j9BZl0JOCY9ATCcegByXRG4jTG4jTG4jr35vmKL26SeTovKoy6EnRMeiJhGPQg5LoDcTpDcTpDcQN3huDnhQcg55IOAY9KIneQJzeQJzeQNzgvTHoScEx6ImEY9CDkugNxOkNxOkNxA3eG4OeFByDnkg4Bj0oid5AnN5AnN5A3OC9MehJwTHoiYRj0IOS6A3E6Q3E6Q3EDd4bg54UHIOeSDgGPSiJ3kCc3kCc3kBc/97knLdbn3JbB3/doCcFx6AnEo5BD0qiNxCnNxCnNxDXvzcppTrnvN18PU4pTQK/btCTgmPQEwnHoAcl0RuI0xuI0xuI69eblNIoOOB1GfSk4Bj0RMIx6EFJ9Abi9Abi9Abieg96k+aovNlLbqfBizDoScEx6ImEY9CDkugNxOkNxOkNxK1k0KtTSptVVVU55x0vuZXjE4OeSDgGPSiJ3kCc3kCc3kDcSga9Sev7UXOU3onmwg/KuQXPt7Jc33r87AdPvnD9jQce2xLpk3cfev7ZD58Yvb3u23BVVRvr/punLt1Mp6/evnby/GtbIn2y8fKtCxuX37tyHHojcgSiNyLx6I1IPHojslyWl1Ia55x3Wt+Pgi+7dYSeFBxH6ImE4wg9KIneQJzeQJzeQFzvQW+z/ZLblNI0pTQOXIRBTwqOQU8kHIMelERvIE5vIE5vIK5/b3LO27MPxWgfrbcgg54UHIOeSDgGPSiJ3kCc3kCc3kDc4L0x6EnBMeiJhGPQg5LoDcTpDcTpDcQN3huDnhQcg55IOAY9KIneQJzeQJzeQNzgvTHoScEx6ImEY9CDkugNxOkNxOkNxA3eG4OeFByDnkg4Bj0oydp78/kbNz539ubNfyqyivz9t9/+i+u+DVfub2AZegNxg/fGoCcFx6AnEo5BD0qy9t6cvXHjt79448bvnH3nnW+L9MkXbtzY2Xrnnb+77ttw5f4GlqE3ELe63qSURimlOvhrBj0pOAY9kXAMelCSQQa9L7zzTvrCO+/cI9InX7xx43cMelAMvYG4lQ56tUFPjlcMeiLhGPSgJAY9KTYGPSiK3kDcanqTUprknHcMenK8YtATCcegByUx6EmxMehBUfQG4vr3Jue8nVKaNv9p0JNjFIOeSDgGPSiJQU+KjUEPiqI3ENe/N7Mxz6Anxy8GPZFwDHpQEoOeFBuDHhRFbyCuX29SSuOU0qSq7hypNxv0TjQXflDOLXi+leX61uNnP3jyhetvPPDYlkifvPvQ889++MTo7XXfhquq2lj33zx16WY6ffX2tZPnX9sS6ZONl29d2Lj83pXj0BuRI5C19+Zzb775e5/53ve+eu9LL22J9MnWW2/9/v3f+c4jx6E3IkcgeiOyXJY3e9+8bgIX4Qg9KTiO0BMJxxF6UJK198YRerKqOEIPiqI3ELe63njJrRy/GPREwjHoQUkMelJsDHpQFL2BOIOeyPIx6ImEY9CDkhj0pNgY9KAoegNxg/fGoCcFx6AnEo5BD0pi0JNiY9CDougNxA3eG4OeFByDnkg4Bj0oiUFPio1BD4qiNxA3eG8MelJwDHoi4Rj0oCQGPSk2Bj0oit5A3OC9MehJwTHoiYRzjAa9+vuPPFP/4JG3RFaThz+97ttwZdCTgmPQg6KstTd1Xf2x+pUzb4msLL/26R9b52240b83KaVpSqlOKdU5553grxv0pOAY9ETCOU6D3q0v//N658vfrn/wyKMiPTOp/9M/eHrdt+HKoCcFx6AHRVnvoPf6w5+oXzlT17/12UdFeueVz/xR/fqnf3ydt+FGv96klCYppXHr+2n7+wUY9KTgGPREwjlug973H3mx/v7D94j0ys6Xv23QE4nFoAdFGWjQ+8w9Ir3zys/9lyIHva5m4JsEfsWgJwXHoCcSjkFPJB6Dnkg4Bj0oikFPys1RGfRyzjuO0JPjE4OeSDgGPZF4DHoi4Rj0oCgGPSk3R2HQSymNU0p18NcMelJwDHoi4Rj0ROIx6ImEY9CDohj0pNyUPuillEbNB2NsBn/VoCcFx6AnEo5BTyQeg55IOAY9KIpBT8pNyYPeHkfmnWgu/KCcW/B8K8v1rcfPfvDkC9ffeOCxLZE+efeh55/98InR2+u+DVdVtbHuv3nq0s10+urtayfPv7Yl0icbL9+6sHH5vSvHoTf/4/qD3/if1x/89hv/enNLpE/e//dfGv/Xf/eFXz4Ovfncm2/+3me+972v3vvSS1sifbL11lu/f/93vvPIcejN5af/z3++8sz/+6HIKvLg3/61v3nUe/PJH/+xn6xfOVO/cf5ntkT65v/+m7/z3577/J/96wP05pNVH82RedMeF+EIPSk4jtATCccReiLxOEJPJJzjdITeONU/uPp0/fO/8ZX6jEif/Poz9c53n6pPrvs2XK25N47Qk5Wm1CP0UkrT5qW2d5Jz3glchEFPCo5BTyQcg55IPAY9kXCO6aB3j0if/Poz9R8Y9ESCKXXQWwGDnhQcg55IOAY9kXgMeiLhGPRE4jHoiSwRg976GPRkdTHoiYRj0BOJx6AnEo5BTyQeg57IEjHorY9BT1YXg55IOAY9kXgMeiLhGPRE4jHoiSwRg976GPRkdTHoiYRj0BOJx6AnEo5BTyQeg57IEjHorY9BT1YXg55IOAY9kXgMeiLhGPRE4jHoiSyRkge9nPN261NuJ8FfN+hJwTHoiYRj0BOJx6AnEo5BTyQeg57IEil50Esp1Tnn7ebraUppFPh1g54UHIOeSDgGPZF4DHoi4Rj0ROIx6IkskVIHvZTSKKU0bX0/zjnvBC7CoCcFx6AnEo5BTyQeg55IOAY9kXgMeiJLpOBBb9eA1x34FmDQk4Jj0BMJx6AnEo9BTyQcg55IPAY9kSVi0Fsfg56sLgY9kXAMeiLxGPREwjHoicRj0BNZIkdw0PtTVVWdWSAb1Y9GvbXl3F8+9U/+8Oefef3Rn/rp50T65Fc+9XNf+w8P/sK/XfdteIj8ub/3S//i5C+++pt/+v4vPSfSJ3/hsZe++deef+Xq0LfpdeRf/dKnvvG737jvu49+/s8/J9Inv/uN+777rV/8mYtD36bXkXsvXfqNv/H889/85Gc/+5xIn9z7rW9d+8mzZ88PfZteR772pf84+fynfuVr9/3Uo8+J9Mk/e/APX//pv/TFXxj6Nn2384lPVA/993/5t3Yevf8nnhPpm1tfv/etv/Jn/uQ/GuC2PPh76J3pdQXgeFr7v/zCEaA3EKc3EKc3EKc3EDf4p9ye6X0F4PhxhwdxegNxegNxegNxegNx/XuTc95OKdVNJsFfP9P7CsDx4w4P4vQG4vQG4vQG4vQG4gbvzZmhrwAUaPDiQoH0BuL0BuL0BuL0BuIG782Zoa8AFGjw4kKB9Abi9Abi9Abi9AbiBu/NmaGvABRo8OJCgfQG4vQG4vQG4vQG4gbvzZmhrwAUaPDiQoH0BuL0BuL0BuL0BuIG782Zoa8AFGjw4kKB9Abi9Abi9Abi9AbiBu/NmaGvABRo8OJCgfQG4vQG4vQG4vQG4gbvzf1DXwEo0E8MfQWgQHoDcXoDcXoDcXoDcXoDAAAAAHBo5Zx3Ukr1nGwuc3kppTrnvL3q6wmHRUpp2u3L7DafUtrs0x8oXUppmnPemffzlNJk3u/knLdTSnX3aziO5jwuGw99neAw2uM5zHTVf8dzG46KlNKk05fR0NcJ6Km5M9z1YDGlNJn3hGwR7vQ46pphYtT6fjQbIAx68KP7gTkd2fNJlkEPfmTe8G3Ug/n2eg6z1z8eLctzG46Cpi93Hou1nrO4f4GS7XFnOOo+oWofldS9U2ut/BN3ehx1cwa9OyPevK9nfZg3VKziqFg4bLr3IbMetPpRt0/fb9Db63faPZzzOxMPUClNSmk8b/hu+jRuvp62jkqa3f7bRyntOtpir9Nmw2H78dvd/u8Hq7bXc5jZQQnt2333H1yb+6Wd1v1T3XRwXl92PbfZ7zkRHEZ7/WNp++ezA3ra9wndo2BnvzcbzlunTTuXO/u9abennZ6574G+FjlCrznPpDlt1xO1eae5c+MomzPo3Tn6KDLoNZcze5I294kclGp235JaR0t0nlzduZ85YNBr92TSeqI2bl3uuHnQuN36HQM5RZn3eKwrdV7SPq9HrcFiv9Oms/uc7mlQinmdaf/soEGvPSa0R4k5fWk/ltvzOREcViml8V6vvmuN2pPO469x5/5m1+OxOX2adW00p0vj1mm7/sE3edkv9LPXe+i1z9N9oNceNLoDnkGPoy4t+B56+w16s9M6l6s7HBmtLrSHunkv9djca9Db52i9zZzzdmus2GkeJI6a8xjHKU53nJh3ZET7CdXs+/b9RmfM2Pe0zuW4/6E4857DdAaIgwa90bzzNt/Pfa6z33MiOKzSPi9Fn92G0wFvudW5D5l38M+4+/W83+vc9+w5NAILmnMYbPcObdfLnVqZPXH62GHoHhRylHUfvLV7sOig1/oXq7nDIBwFnQdxoz3uS/Yc9NLH/yX3Y0/IWn9ns3mgONrrQSscZnsdodfuwbwhbk7GC5xm0KN4Bx3V2mfQ6x7pN+9tI9rPie7ef0vob7/hrHX7/tigt899yFKD3kEjPLCEOaX72Esvut+3zRn0PCjkSOsOelW16+WF896jZaEj9OCo6TyI23WEXud84SP0Wpd/Z8CbvRTKfRAlSvu/h95CR+h1fm/f0wx6lG6BQe/O47XooJcWPEIPShB5D73ZaalzVN/dOEIPWIEl3kNvs3PH1n5PI++hx5HXHfTSHkfoNaftes+wzjgxTbvHDg8SOVL2OwK8PVJE3kMv7X7Z7mg26rX+npfbUqzUeY+85mf7veS2+wRs7vtUzjnNoEfxFhz02u9VvO+gt897Tu71Hnofe6USHFbdx0it5yz7jXSzfzDtvhfenoNemv/e4nPfQ6/9N4Al7fMSjzp1/hV49qAydY5Omp02+38U7tg4yjpd6B6C3h302i8z3DXoNad7uS1H1pxBr/typdmRduFPuW2f1voHJu/FQvFS2vXJgfMei837EICPnXe/0wx6HAUHDXqdtzfZ8038Z9+3+7Lfq4/2e04Eh9mc+5d2B7oj3XarDzvtx1j7DXqt7+t0wKfceswGAAAALM04B3eHfzACAAAA7gqDHqzGfkeZAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQMn+P29gGWJmBRCLAAAAAElFTkSuQmCC \ No newline at end of file +data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAB2gAAAEsCAYAAAAGmePsAAAgAElEQVR4XuzdD5Ql1X0f+H7dIxiZGckeUPCMkDhBf9gVcqT1EMVowQOyIjmskVFQFB+02IFNujM6WttCOMSxAoNixbEPIB17o053dMC7ZIhXThYM8SIt8QokNlFkxhzpGJkBRCxGnokUgRbNgNZIPW9/1Xlv8rqn/7z3qurVrapPn1Nnut+run8+93Kpft+uqs6ULwIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBCYiEBnIrWohAABAgQIECBAgAABAgQIECBAgAABAgQIECBAgAABAgSmBLQmAQECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBCYkIKCdELRqCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgIKA1BwgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIDAhAQHthKBVQ4AAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQGtOUCAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAIEJCQhoJwStGgIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECAhozQECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECBAhMSEBAOyFo1RAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQEBAaw4QIECAAAECBAgQIECAAAECBAgQIECAAAECBAgQIEBgQgIC2glBq4YAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQICWnOAAAECBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECExIQ0E4IWjUECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAQ0JoDBAgQIECAAAECBAgQSESgO/uPXjO11PlkIs2ZXDNmtvxcZ/HvPz25CtVEgAABAgQIECBAgAABAgSqExDQVmevZgIECBAgQIAAAQIECKwQ6P5PH/2Jqanuv53qTP3ZVLf7n5rPM70z+rtrqnP8xzufvOHzze+vHhIgQIAAAQIECBAgQIAAgan4td8XAQIECBAgQIAAAQIECCQhcCKgnTr+d+K3tUeSaFSZjehM/+Wp41Pzowa0c3NzD0ez/unCwsLtWfNmZ2fviX8OLC4u3lRE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 \ No newline at end of file diff --git a/src/test/resources/libraries/chartjs/2.9.4/expectations/simple_bar_chart.IE.expected b/src/test/resources/libraries/chartjs/2.9.4/expectations/simple_bar_chart.IE.expected deleted file mode 100644 index 18279504da1..00000000000 --- a/src/test/resources/libraries/chartjs/2.9.4/expectations/simple_bar_chart.IE.expected +++ /dev/null @@ -1 +0,0 @@ -data:image/png;base64,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 \ No newline at end of file diff --git a/src/test/resources/libraries/chartjs/2.9.4/expectations/simple_bar_chart.IE_NYI.expected b/src/test/resources/libraries/chartjs/2.9.4/expectations/simple_bar_chart.IE_NYI.expected deleted file mode 100644 index e8cc4bde001..00000000000 --- a/src/test/resources/libraries/chartjs/2.9.4/expectations/simple_bar_chart.IE_NYI.expected +++ /dev/null @@ -1 +0,0 @@ -data:image/png;base64,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 \ No newline at end of file diff --git a/src/test/resources/libraries/dojo/1.0.2/expectations/testsbehavior.IE.txt b/src/test/resources/libraries/dojo/1.0.2/expectations/testsbehavior.IE.txt deleted file mode 100644 index 894ca404cfd..00000000000 --- a/src/test/resources/libraries/dojo/1.0.2/expectations/testsbehavior.IE.txt +++ /dev/null @@ -1,39 +0,0 @@ - 1 tests to run in 1 groups - ------------------------------------------------------------ - GROUP "tests.behavior" has 1 test to run - 4 tests to run in 1 groups - ------------------------------------------------------------ - GROUP "t" has 4 tests to run - PASSED test: ../../dojo/tests/behavior.html::t::add - PASSED test: ../../dojo/tests/behavior.html::t::apply - PASSED test: ../../dojo/tests/behavior.html::t::reapply - _AssertFailure: doh._AssertFailure: assertEqual() failed: expected |3| but got |2|: assertEqual() failed: expected |3| but got |2| - doh._AssertFailure: assertEqual() failed: expected |3| but got |2| - ERROR IN: - function topics(t){ - t.is(0, topicCount); - dojo.behavior.add({ ".foo": "/foo" }); - dojo.behavior.apply(); - t.is(2, topicCount); - - dojo.behavior.add({ ".foo": { - "onfocus": "/foo" - } - }); - dojo.behavior.apply(); - t.is(2, topicCount); - dojo.byId("blah").focus(); - t.is(3, topicCount); - dojo.byId("blah").blur(); - dojo.byId("blah").focus(); - t.is(4, topicCount); - - } - FAILED test: ../../dojo/tests/behavior.html::t::topics - PASSED test: ../../dojo/tests/behavior.html - ------------------------------------------------------------ - | TEST SUMMARY: - ------------------------------------------------------------ - 5 tests in 2 groups - 0 errors - 1 failures diff --git a/src/test/resources/libraries/dojo/1.0.2/expectations/testsbehavior.IE_NYI.txt b/src/test/resources/libraries/dojo/1.0.2/expectations/testsbehavior.IE_NYI.txt deleted file mode 100644 index 2ca48fbc1ec..00000000000 --- a/src/test/resources/libraries/dojo/1.0.2/expectations/testsbehavior.IE_NYI.txt +++ /dev/null @@ -1,18 +0,0 @@ - 1 tests to run in 1 groups - ------------------------------------------------------------ - GROUP "tests.behavior" has 1 test to run - 4 tests to run in 1 groups - ------------------------------------------------------------ - GROUP "t" has 4 tests to run - PASSED test: ../../dojo/tests/behavior.html::t::add - PASSED test: ../../dojo/tests/behavior.html::t::apply - PASSED test: ../../dojo/tests/behavior.html::t::reapply - PASSED test: ../../dojo/tests/behavior.html::t::topics - PASSED test: ../../dojo/tests/behavior.html - WOOHOO!! - ------------------------------------------------------------ - | TEST SUMMARY: - ------------------------------------------------------------ - 5 tests in 2 groups - 0 errors - 0 failures diff --git a/src/test/resources/libraries/dojo/1.0.2/expectations/testsrpc.IE.txt b/src/test/resources/libraries/dojo/1.0.2/expectations/testsrpc.IE.txt deleted file mode 100644 index 1f299793dff..00000000000 --- a/src/test/resources/libraries/dojo/1.0.2/expectations/testsrpc.IE.txt +++ /dev/null @@ -1,42 +0,0 @@ - 4 tests to run in 1 groups - ------------------------------------------------------------ - GROUP "tests.rpc" has 4 tests to run - PASSED test: JsonRPC-EchoTest - PASSED test: JsonRPC-EmptyParamTest - PASSED test: JsonRPC_SMD_Loading_test - TypeError: Das Objekt unterstützt die Eigenschaft oder Methode "webSearch" nicht - ERROR IN: - function(){ - var d = new doh.Deferred(); - - if (window.location.protocol=="file:") { - var err= new Error("This Test requires a webserver and will fail intentionally if loaded from file://"); - d.errback(err); - return d; - } - - var td = this.svc.webSearch({query:"dojotoolkit"}); - - td.addCallbacks(function(result){ - return true; - if (result["ResultSet"]["Result"][0]["DisplayUrl"]=="dojotoolkit.org/") { - return true; - }else{ - return new Error("JsonRpc_SMD_Loading_Test failed, resultant content didn't match"); - } - }, function(result){ - return new Error(result); - }); - - td.addBoth(d, "callback"); - - return d; - } - FAILED test: JsonP_test - WOOHOO!! - ------------------------------------------------------------ - | TEST SUMMARY: - ------------------------------------------------------------ - 4 tests in 1 groups - 1 errors - 0 failures diff --git a/src/test/resources/libraries/dojo/1.9.3/expectations/dojo_tests_base_html.IE.txt b/src/test/resources/libraries/dojo/1.9.3/expectations/dojo_tests_base_html.IE.txt deleted file mode 100644 index b53c708358f..00000000000 --- a/src/test/resources/libraries/dojo/1.9.3/expectations/dojo_tests_base_html.IE.txt +++ /dev/null @@ -1,310 +0,0 @@ - 9 tests to run in 9 groups - ------------------------------------------------------------ - GROUP "tests._base.html" has 1 test to run - 103 tests to run in 7 groups - ------------------------------------------------------------ - GROUP "t" has 97 tests to run - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(null, dojo.byId('nonExistantId')); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(null, dojo.byId(null)); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(null, dojo.byId('')); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(undefined, dojo.byId(undefined)); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo.marginBox('sq100').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo.marginBox('sq100').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo._getMarginSize('sq100').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo._getMarginSize('sq100').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(120, dojo.marginBox('sq100margin10').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(120, dojo.marginBox('sq100margin10').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo.contentBox('sq100margin10').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo.contentBox('sq100margin10').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(140, dojo.marginBox('sq100margin10pad10').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(140, dojo.marginBox('sq100margin10pad10').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(140, dojo._getMarginSize('sq100margin10pad10').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(140, dojo._getMarginSize('sq100margin10pad10').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(120, dojo.marginBox('sq100pad10').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(120, dojo.marginBox('sq100pad10').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(110, dojo.marginBox('sq100ltpad10').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(110, dojo.marginBox('sq100ltpad10').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo.contentBox('sq100ltpad10').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo.contentBox('sq100ltpad10').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(120, dojo.marginBox('sq100ltpad10rbmargin10').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(120, dojo.marginBox('sq100ltpad10rbmargin10').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(120, dojo.marginBox('sq100border10').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(120, dojo.marginBox('sq100border10').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo.contentBox('sq100border10').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo.contentBox('sq100border10').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(140, dojo.marginBox('sq100border10margin10').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(140, dojo.marginBox('sq100border10margin10').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo.contentBox('sq100border10margin10').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo.contentBox('sq100border10margin10').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(160, dojo.marginBox('sq100border10margin10pad10').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(160, dojo.marginBox('sq100border10margin10pad10').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo.contentBox('sq100border10margin10pad10').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo.contentBox('sq100border10margin10pad10').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo.marginBox('sq100nopos').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(10, dojo._getPadExtents(dojo.byId('sq100ltpad10rbmargin10')).l); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(10, dojo._getPadExtents(dojo.byId('sq100ltpad10rbmargin10')).t); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(10, dojo._getPadExtents(dojo.byId('sq100ltpad10rbmargin10')).w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(10, dojo._getPadExtents(dojo.byId('sq100ltpad10rbmargin10')).h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(0, dojo._getMarginExtents(dojo.byId('sq100ltpad10rbmargin10')).l); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(0, dojo._getMarginExtents(dojo.byId('sq100ltpad10rbmargin10')).t); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(10, dojo._getMarginExtents(dojo.byId('sq100ltpad10rbmargin10')).w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(10, dojo._getMarginExtents(dojo.byId('sq100ltpad10rbmargin10')).h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(10, dojo._getBorderExtents(dojo.byId('sq100border10margin10pad10')).l); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(10, dojo._getBorderExtents(dojo.byId('sq100border10margin10pad10')).t); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(20, dojo._getBorderExtents(dojo.byId('sq100border10margin10pad10')).w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(20, dojo._getBorderExtents(dojo.byId('sq100border10margin10pad10')).h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(20, dojo._getPadBorderExtents(dojo.byId('sq100border10margin10pad10')).l); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(20, dojo._getPadBorderExtents(dojo.byId('sq100border10margin10pad10')).t); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(40, dojo._getPadBorderExtents(dojo.byId('sq100border10margin10pad10')).w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(40, dojo._getPadBorderExtents(dojo.byId('sq100border10margin10pad10')).h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::scrollUp x ms - PASSED test: ../../dojo/tests/_base/html.html::t::coordsBasic x ms - PASSED test: ../../dojo/tests/_base/html.html::t::coordsMargin x ms - PASSED test: ../../dojo/tests/_base/html.html::t::coordsBorder x ms - PASSED test: ../../dojo/tests/_base/html.html::t::sq100nopos x ms - PASSED test: ../../dojo/tests/_base/html.html::t::coordsScrolled x ms - PASSED test: ../../dojo/tests/_base/html.html::t::coordsIframe x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(1, dojo.style('sq100nopos', 'opacity')); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is((0.1).toFixed(4), Number(dojo.style('sq100nopos', 'opacity', 0.1)).toFixed(4)); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is((0.8).toFixed(4), Number(dojo.style('sq100nopos', 'opacity', 0.8)).toFixed(4)); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::styleObject x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is('static', dojo.style('sq100nopos', 'position')); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::getBgcolor x ms - PASSED test: ../../dojo/tests/_base/html.html::t::isDescendant x ms - PASSED test: ../../dojo/tests/_base/html.html::t::isDescendantIframe x ms - PASSED test: ../../dojo/tests/_base/html.html::t::testClassFunctions x ms - PASSED test: ../../dojo/tests/_base/html.html::t::testAddRemoveClassMultiple x ms - PASSED test: ../../dojo/tests/_base/html.html::t::getTypeInput x ms - PASSED test: ../../dojo/tests/_base/html.html::t::getWithString x ms - PASSED test: ../../dojo/tests/_base/html.html::t::attrId x ms - PASSED test: ../../dojo/tests/_base/html.html::t::getTabindexDiv x ms - PASSED test: ../../dojo/tests/_base/html.html::t::getTabindexInput x ms - PASSED test: ../../dojo/tests/_base/html.html::t::setTabindexDiv x ms - PASSED test: ../../dojo/tests/_base/html.html::t::setTabindexInput x ms - PASSED test: ../../dojo/tests/_base/html.html::t::removeTabindexFromDiv x ms - PASSED test: ../../dojo/tests/_base/html.html::t::removeDisabledFromInput x ms - PASSED test: ../../dojo/tests/_base/html.html::t::removeTabindexFromInput x ms - PASSED test: ../../dojo/tests/_base/html.html::t::setReadonlyInput x ms - PASSED test: ../../dojo/tests/_base/html.html::t::attr_map x ms - PASSED test: ../../dojo/tests/_base/html.html::t::attr_reconnect x ms - PASSED test: ../../dojo/tests/_base/html.html::t::attrSpecials x ms - PASSED test: ../../dojo/tests/_base/html.html::t::testLabelForAttr x ms - PASSED test: ../../dojo/tests/_base/html.html::t::attrInnerHtmlDiv x ms - PASSED test: ../../dojo/tests/_base/html.html::t::attrInnerHtmlTable x ms - PASSED test: ../../dojo/tests/_base/html.html::t::attrInputTextValue x ms - PASSED test: ../../dojo/tests/_base/html.html::t::testInputDisabled x ms - PASSED test: ../../dojo/tests/_base/html.html::t::testIframeDestroy10095 x ms - PASSED test: ../../dojo/tests/_base/html.html::t::testGCSsvg x ms - PASSED test: ../../dojo/tests/_base/html.html::t::emptySvg x ms - PASSED test: ../../dojo/tests/_base/html.html::t::destroySvg x ms - PASSED test: ../../dojo/tests/_base/html.html::t::emptyObject x ms - PASSED test: ../../dojo/tests/_base/html.html::t::destroyObject x ms - PASSED test: ../../dojo/tests/_base/html.html::t::destroyIframe x ms - PASSED test: ../../dojo/tests/_base/html.html::t::destroyDivNotInDOM x ms - ------------------------------------------------------------ - GROUP "scrollingQuirksIframeNone" has 1 test to run - PASSED test: ../../dojo/tests/_base/html.html::scrollingQuirksIframeNone::test_scrollingQuirksIframeNone x ms - ------------------------------------------------------------ - GROUP "scrollingStrictIframeNone" has 1 test to run - PASSED test: ../../dojo/tests/_base/html.html::scrollingStrictIframeNone::test_scrollingStrictIframeNone x ms - ------------------------------------------------------------ - GROUP "scrollingQuirksIframeVert" has 1 test to run - PASSED test: ../../dojo/tests/_base/html.html::scrollingQuirksIframeVert::test_scrollingQuirksIframeVert x ms - ------------------------------------------------------------ - GROUP "scrollingStrictIframeVert" has 1 test to run - PASSED test: ../../dojo/tests/_base/html.html::scrollingStrictIframeVert::test_scrollingStrictIframeVert x ms - ------------------------------------------------------------ - GROUP "scrollingQuirksIframeBoth" has 1 test to run - PASSED test: ../../dojo/tests/_base/html.html::scrollingQuirksIframeBoth::test_scrollingQuirksIframeBoth x ms - ------------------------------------------------------------ - GROUP "scrollingStrictIframeBoth" has 1 test to run - PASSED test: ../../dojo/tests/_base/html.html::scrollingStrictIframeBoth::test_scrollingStrictIframeBoth x ms - PASSED test: ../../dojo/tests/_base/html.html x ms - ------------------------------------------------------------ - GROUP "tests._base.html_id" has 1 test to run - 1 tests to run in 1 groups - ------------------------------------------------------------ - GROUP "t" has 1 test to run - PASSED test: ../../dojo/tests/_base/html_id.html::t::byId x ms - PASSED test: ../../dojo/tests/_base/html_id.html x ms - ------------------------------------------------------------ - GROUP "tests._base.html_element" has 1 test to run - 21 tests to run in 1 groups - ------------------------------------------------------------ - GROUP "t" has 21 tests to run - PASSED test: ../../dojo/tests/_base/html_element.html::t::createBasic x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::createAttrs x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::createPlace x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::createHtml x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::createPlaceRef x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::destroyList x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::createList x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::destroyAll x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::recreateOneV1 x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::recreateOneV2 x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::emptyDiv x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::emptyTable x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::toDomSpans x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::toDomTr x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::toDomText x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::toDomOption x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::placeDivs x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::placeTable x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::placeReplace x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::placeOnly x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::placeNumber x ms - PASSED test: ../../dojo/tests/_base/html_element.html x ms - ------------------------------------------------------------ - GROUP "tests._base.html_rtl" has 1 test to run - 19 tests to run in 17 groups - ------------------------------------------------------------ - GROUP "rtl" has 3 tests to run - PASSED test: ../../dojo/tests/_base/html_rtl.html::rtl::coordsWithScrolling x ms - PASSED test: ../../dojo/tests/_base/html_rtl.html::rtl::eventClientXY_IE x ms - PASSED test: ../../dojo/tests/_base/html_rtl.html::rtl::testScrolledPosition x ms - ------------------------------------------------------------ - GROUP "scrollingQuirksIframeNoneSmall" has 1 test to run - PASSED test: ../../dojo/tests/_base/html_rtl.html::scrollingQuirksIframeNoneSmall::test_scrollingQuirksIframeNoneSmall x ms - ------------------------------------------------------------ - GROUP "scrollingQuirksIframeNoneLarge" has 1 test to run - PASSED test: ../../dojo/tests/_base/html_rtl.html::scrollingQuirksIframeNoneLarge::test_scrollingQuirksIframeNoneLarge x ms - ------------------------------------------------------------ - GROUP "scrollingStrictIframeNoneSmall" has 1 test to run - PASSED test: ../../dojo/tests/_base/html_rtl.html::scrollingStrictIframeNoneSmall::test_scrollingStrictIframeNoneSmall x ms - ------------------------------------------------------------ - GROUP "scrollingStrictIframeNoneLarge" has 1 test to run - PASSED test: ../../dojo/tests/_base/html_rtl.html::scrollingStrictIframeNoneLarge::test_scrollingStrictIframeNoneLarge x ms - ------------------------------------------------------------ - GROUP "scrollingQuirksIframeHorzSmall" has 1 test to run - PASSED test: ../../dojo/tests/_base/html_rtl.html::scrollingQuirksIframeHorzSmall::test_scrollingQuirksIframeHorzSmall x ms - ------------------------------------------------------------ - GROUP "scrollingQuirksIframeHorzLarge" has 1 test to run - PASSED test: ../../dojo/tests/_base/html_rtl.html::scrollingQuirksIframeHorzLarge::test_scrollingQuirksIframeHorzLarge x ms - ------------------------------------------------------------ - GROUP "scrollingStrictIframeHorzSmall" has 1 test to run - PASSED test: ../../dojo/tests/_base/html_rtl.html::scrollingStrictIframeHorzSmall::test_scrollingStrictIframeHorzSmall x ms - ------------------------------------------------------------ - GROUP "scrollingStrictIframeHorzLarge" has 1 test to run - PASSED test: ../../dojo/tests/_base/html_rtl.html::scrollingStrictIframeHorzLarge::test_scrollingStrictIframeHorzLarge x ms - ------------------------------------------------------------ - GROUP "scrollingQuirksIframeVertSmall" has 1 test to run - PASSED test: ../../dojo/tests/_base/html_rtl.html::scrollingQuirksIframeVertSmall::test_scrollingQuirksIframeVertSmall x ms - ------------------------------------------------------------ - GROUP "scrollingQuirksIframeVertLarge" has 1 test to run - PASSED test: ../../dojo/tests/_base/html_rtl.html::scrollingQuirksIframeVertLarge::test_scrollingQuirksIframeVertLarge x ms - ------------------------------------------------------------ - GROUP "scrollingStrictIframeVertSmall" has 1 test to run - PASSED test: ../../dojo/tests/_base/html_rtl.html::scrollingStrictIframeVertSmall::test_scrollingStrictIframeVertSmall x ms - ------------------------------------------------------------ - GROUP "scrollingStrictIframeVertLarge" has 1 test to run - PASSED test: ../../dojo/tests/_base/html_rtl.html::scrollingStrictIframeVertLarge::test_scrollingStrictIframeVertLarge x ms - ------------------------------------------------------------ - GROUP "scrollingQuirksIframeBothSmall" has 1 test to run - PASSED test: ../../dojo/tests/_base/html_rtl.html::scrollingQuirksIframeBothSmall::test_scrollingQuirksIframeBothSmall x ms - ------------------------------------------------------------ - GROUP "scrollingQuirksIframeBothLarge" has 1 test to run - PASSED test: ../../dojo/tests/_base/html_rtl.html::scrollingQuirksIframeBothLarge::test_scrollingQuirksIframeBothLarge x ms - ------------------------------------------------------------ - GROUP "scrollingStrictIframeBothSmall" has 1 test to run - PASSED test: ../../dojo/tests/_base/html_rtl.html::scrollingStrictIframeBothSmall::test_scrollingStrictIframeBothSmall x ms - ------------------------------------------------------------ - GROUP "scrollingStrictIframeBothLarge" has 1 test to run - PASSED test: ../../dojo/tests/_base/html_rtl.html::scrollingStrictIframeBothLarge::test_scrollingStrictIframeBothLarge x ms - PASSED test: ../../dojo/tests/_base/html_rtl.html x ms - ------------------------------------------------------------ - GROUP "tests._base.html_quirks" has 1 test to run - 39 tests to run in 1 groups - ------------------------------------------------------------ - GROUP "t" has 39 tests to run - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(100, dojo.marginBox('sq100').w); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(100, dojo.marginBox('sq100').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(120, dojo.marginBox('sq100margin10').w); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(120, dojo.marginBox('sq100margin10').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(100, dojo.contentBox('sq100margin10').w); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(100, dojo.contentBox('sq100margin10').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(100, dojo.marginBox('sq100nopos').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::coordsBasic x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::coordsMargin x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::coordsBorder x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::sq100nopos x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(140, dojo.marginBox('sq100margin10pad10').w); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(140, dojo.marginBox('sq100margin10pad10').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(120, dojo.marginBox('sq100pad10').w); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(120, dojo.marginBox('sq100pad10').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(110, dojo.marginBox('sq100ltpad10').w); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(110, dojo.marginBox('sq100ltpad10').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(100, dojo.contentBox('sq100ltpad10').w); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(100, dojo.contentBox('sq100ltpad10').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(120, dojo.marginBox('sq100ltpad10rbmargin10').w); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(120, dojo.marginBox('sq100ltpad10rbmargin10').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(120, dojo.marginBox('sq100border10').w); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(120, dojo.marginBox('sq100border10').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(100, dojo.contentBox('sq100border10').w); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(100, dojo.contentBox('sq100border10').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(140, dojo.marginBox('sq100border10margin10').w); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(140, dojo.marginBox('sq100border10margin10').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(100, dojo.contentBox('sq100border10margin10').w); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(100, dojo.contentBox('sq100border10margin10').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(160, dojo.marginBox('sq100border10margin10pad10').w); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(160, dojo.marginBox('sq100border10margin10pad10').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(100, dojo.contentBox('sq100border10margin10pad10').w); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(100, dojo.contentBox('sq100border10margin10pad10').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::emptySvg x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::destroySvg x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::emptyObject x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::destroyObject x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::destroyIframe x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::destroyDivNotInDOM x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html x ms - ------------------------------------------------------------ - GROUP "tests._base.html_box" has 1 test to run - 6 tests to run in 1 groups - ------------------------------------------------------------ - GROUP "t" has 6 tests to run - PASSED test: ../../dojo/tests/_base/html_box.html::t::reciprocalTests x ms - PASSED test: ../../dojo/tests/_base/html_box.html::t::fitTests x ms - PASSED test: ../../dojo/tests/_base/html_box.html::t::fitTestsOverflow x ms - PASSED test: ../../dojo/tests/_base/html_box.html::t::fitTestsFloat x ms - PASSED test: ../../dojo/tests/_base/html_box.html::t::reciprocalTestsInline x ms - PASSED test: ../../dojo/tests/_base/html_box.html::t::reciprocalTestsButtonChild x ms - PASSED test: ../../dojo/tests/_base/html_box.html x ms - ------------------------------------------------------------ - GROUP "tests._base.html_box_quirks" has 1 test to run - 6 tests to run in 1 groups - ------------------------------------------------------------ - GROUP "t" has 6 tests to run - PASSED test: ../../dojo/tests/_base/html_box_quirks.html::t::reciprocalTests x ms - PASSED test: ../../dojo/tests/_base/html_box_quirks.html::t::fitTests x ms - PASSED test: ../../dojo/tests/_base/html_box_quirks.html::t::fitTestsOverflow x ms - PASSED test: ../../dojo/tests/_base/html_box_quirks.html::t::fitTestsFloat x ms - PASSED test: ../../dojo/tests/_base/html_box_quirks.html::t::reciprocalTestsInline x ms - PASSED test: ../../dojo/tests/_base/html_box_quirks.html::t::reciprocalTestsButtonChild x ms - PASSED test: ../../dojo/tests/_base/html_box_quirks.html x ms - ------------------------------------------------------------ - GROUP "tests._base.html_isBodyLtr" has 1 test to run - 5 tests to run in 1 groups - ------------------------------------------------------------ - GROUP "t" has 5 tests to run - PASSED test: ../../dojo/tests/_base/html_isBodyLtr.html::t::testRtl x ms - PASSED test: ../../dojo/tests/_base/html_isBodyLtr.html::t::testCache x ms - PASSED test: ../../dojo/tests/_base/html_isBodyLtr.html::t::testHtmlValue x ms - PASSED test: ../../dojo/tests/_base/html_isBodyLtr.html::t::testDefaultValue x ms - PASSED test: ../../dojo/tests/_base/html_isBodyLtr.html::t::testHiddenIframe x ms - PASSED test: ../../dojo/tests/_base/html_isBodyLtr.html x ms - ------------------------------------------------------------ - GROUP "tests._base.html_docScroll" has 1 test to run - 4 tests to run in 1 groups - ------------------------------------------------------------ - GROUP "t" has 4 tests to run - PASSED test: ../../dojo/tests/_base/html_docScroll.html::t::testNonScrolled x ms - PASSED test: ../../dojo/tests/_base/html_docScroll.html::t::testScrolled x ms - PASSED test: ../../dojo/tests/_base/html_docScroll.html::t::testQuirksNonScrolled x ms - PASSED test: ../../dojo/tests/_base/html_docScroll.html::t::testQuirksScrolled x ms - PASSED test: ../../dojo/tests/_base/html_docScroll.html x ms - WOOHOO!! - ------------------------------------------------------------ - | TEST SUMMARY: - ------------------------------------------------------------ - 213 tests in 9 groups - 0 errors - 0 failures diff --git a/src/test/resources/libraries/dojo/1.9.3/expectations/dojo_tests_base_html.IE_NYI.txt b/src/test/resources/libraries/dojo/1.9.3/expectations/dojo_tests_base_html.IE_NYI.txt deleted file mode 100644 index 48535f37aab..00000000000 --- a/src/test/resources/libraries/dojo/1.9.3/expectations/dojo_tests_base_html.IE_NYI.txt +++ /dev/null @@ -1,501 +0,0 @@ -9 tests to run in 9 groups - ------------------------------------------------------------ - GROUP "tests._base.html" has 1 test to run - 103 tests to run in 7 groups - ------------------------------------------------------------ - GROUP "t" has 97 tests to run - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(null, dojo.byId('nonExistantId')); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(null, dojo.byId(null)); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(null, dojo.byId('')); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(undefined, dojo.byId(undefined)); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo.marginBox('sq100').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo.marginBox('sq100').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo._getMarginSize('sq100').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo._getMarginSize('sq100').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(120, dojo.marginBox('sq100margin10').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(120, dojo.marginBox('sq100margin10').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo.contentBox('sq100margin10').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo.contentBox('sq100margin10').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(140, dojo.marginBox('sq100margin10pad10').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(140, dojo.marginBox('sq100margin10pad10').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(140, dojo._getMarginSize('sq100margin10pad10').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(140, dojo._getMarginSize('sq100margin10pad10').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(120, dojo.marginBox('sq100pad10').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(120, dojo.marginBox('sq100pad10').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(110, dojo.marginBox('sq100ltpad10').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(110, dojo.marginBox('sq100ltpad10').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo.contentBox('sq100ltpad10').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo.contentBox('sq100ltpad10').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(120, dojo.marginBox('sq100ltpad10rbmargin10').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(120, dojo.marginBox('sq100ltpad10rbmargin10').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(120, dojo.marginBox('sq100border10').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(120, dojo.marginBox('sq100border10').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo.contentBox('sq100border10').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo.contentBox('sq100border10').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(140, dojo.marginBox('sq100border10margin10').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(140, dojo.marginBox('sq100border10margin10').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo.contentBox('sq100border10margin10').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo.contentBox('sq100border10margin10').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(160, dojo.marginBox('sq100border10margin10pad10').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(160, dojo.marginBox('sq100border10margin10pad10').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo.contentBox('sq100border10margin10pad10').w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo.contentBox('sq100border10margin10pad10').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(100, dojo.marginBox('sq100nopos').h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(10, dojo._getPadExtents(dojo.byId('sq100ltpad10rbmargin10')).l); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(10, dojo._getPadExtents(dojo.byId('sq100ltpad10rbmargin10')).t); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(10, dojo._getPadExtents(dojo.byId('sq100ltpad10rbmargin10')).w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(10, dojo._getPadExtents(dojo.byId('sq100ltpad10rbmargin10')).h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(0, dojo._getMarginExtents(dojo.byId('sq100ltpad10rbmargin10')).l); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(0, dojo._getMarginExtents(dojo.byId('sq100ltpad10rbmargin10')).t); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(10, dojo._getMarginExtents(dojo.byId('sq100ltpad10rbmargin10')).w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(10, dojo._getMarginExtents(dojo.byId('sq100ltpad10rbmargin10')).h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(10, dojo._getBorderExtents(dojo.byId('sq100border10margin10pad10')).l); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(10, dojo._getBorderExtents(dojo.byId('sq100border10margin10pad10')).t); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(20, dojo._getBorderExtents(dojo.byId('sq100border10margin10pad10')).w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(20, dojo._getBorderExtents(dojo.byId('sq100border10margin10pad10')).h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(20, dojo._getPadBorderExtents(dojo.byId('sq100border10margin10pad10')).l); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(20, dojo._getPadBorderExtents(dojo.byId('sq100border10margin10pad10')).t); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(40, dojo._getPadBorderExtents(dojo.byId('sq100border10margin10pad10')).w); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(40, dojo._getPadBorderExtents(dojo.byId('sq100border10margin10pad10')).h); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::scrollUp x ms - PASSED test: ../../dojo/tests/_base/html.html::t::coordsBasic x ms - PASSED test: ../../dojo/tests/_base/html.html::t::coordsMargin x ms - PASSED test: ../../dojo/tests/_base/html.html::t::coordsBorder x ms - PASSED test: ../../dojo/tests/_base/html.html::t::sq100nopos x ms - PASSED test: ../../dojo/tests/_base/html.html::t::coordsScrolled x ms - _AssertFailure: assertTrue('false') failed with hint: - quirks iframe element x == 0 (x,y,w,h=2,2,174,22) - ERROR IN: function... - FAILED test: ../../dojo/tests/_base/html.html::t::coordsIframe x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is(1, dojo.style('sq100nopos', 'opacity')); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is((0.1).toFixed(4), Number(dojo.style('sq100nopos', 'opacity', 0.1)).toFixed(4)); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is((0.8).toFixed(4), Number(dojo.style('sq100nopos', 'opacity', 0.8)).toFixed(4)); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::styleObject x ms - PASSED test: ../../dojo/tests/_base/html.html::t::doh.is('static', dojo.style('sq100nopos', 'position')); x ms - PASSED test: ../../dojo/tests/_base/html.html::t::getBgcolor x ms - PASSED test: ../../dojo/tests/_base/html.html::t::isDescendant x ms - PASSED test: ../../dojo/tests/_base/html.html::t::isDescendantIframe x ms - PASSED test: ../../dojo/tests/_base/html.html::t::testClassFunctions x ms - PASSED test: ../../dojo/tests/_base/html.html::t::testAddRemoveClassMultiple x ms - PASSED test: ../../dojo/tests/_base/html.html::t::getTypeInput x ms - PASSED test: ../../dojo/tests/_base/html.html::t::getWithString x ms - PASSED test: ../../dojo/tests/_base/html.html::t::attrId x ms - PASSED test: ../../dojo/tests/_base/html.html::t::getTabindexDiv x ms - PASSED test: ../../dojo/tests/_base/html.html::t::getTabindexInput x ms - PASSED test: ../../dojo/tests/_base/html.html::t::setTabindexDiv x ms - PASSED test: ../../dojo/tests/_base/html.html::t::setTabindexInput x ms - PASSED test: ../../dojo/tests/_base/html.html::t::removeTabindexFromDiv x ms - PASSED test: ../../dojo/tests/_base/html.html::t::removeDisabledFromInput x ms - PASSED test: ../../dojo/tests/_base/html.html::t::removeTabindexFromInput x ms - PASSED test: ../../dojo/tests/_base/html.html::t::setReadonlyInput x ms - PASSED test: ../../dojo/tests/_base/html.html::t::attr_map x ms - PASSED test: ../../dojo/tests/_base/html.html::t::attr_reconnect x ms - _AssertFailure: assertEqual() failed: - expected - 1 - but got - 0 - - ERROR IN: function... - FAILED test: ../../dojo/tests/_base/html.html::t::attrSpecials x ms - PASSED test: ../../dojo/tests/_base/html.html::t::testLabelForAttr x ms - PASSED test: ../../dojo/tests/_base/html.html::t::attrInnerHtmlDiv x ms - PASSED test: ../../dojo/tests/_base/html.html::t::attrInnerHtmlTable x ms - PASSED test: ../../dojo/tests/_base/html.html::t::attrInputTextValue x ms - PASSED test: ../../dojo/tests/_base/html.html::t::testInputDisabled x ms - PASSED test: ../../dojo/tests/_base/html.html::t::testIframeDestroy10095 x ms - PASSED test: ../../dojo/tests/_base/html.html::t::testGCSsvg x ms - PASSED test: ../../dojo/tests/_base/html.html::t::emptySvg x ms - PASSED test: ../../dojo/tests/_base/html.html::t::destroySvg x ms - PASSED test: ../../dojo/tests/_base/html.html::t::emptyObject x ms - PASSED test: ../../dojo/tests/_base/html.html::t::destroyObject x ms - PASSED test: ../../dojo/tests/_base/html.html::t::destroyIframe x ms - PASSED test: ../../dojo/tests/_base/html.html::t::destroyDivNotInDOM x ms - ------------------------------------------------------------ - GROUP "scrollingQuirksIframeNone" has 1 test to run - _AssertFailure: assertEqual() failed: - expected - EQUAL - but got - abs1.offsetTop=36 control.offsetTop=54 - - ERROR IN: function... - FAILED test: ../../dojo/tests/_base/html.html::scrollingQuirksIframeNone::test_scrollingQuirksIframeNone x ms - ------------------------------------------------------------ - GROUP "scrollingStrictIframeNone" has 1 test to run - _AssertFailure: assertEqual() failed: - expected - EQUAL - but got - abs1.offsetTop=36 control.offsetTop=54 - - ERROR IN: function... - FAILED test: ../../dojo/tests/_base/html.html::scrollingStrictIframeNone::test_scrollingStrictIframeNone x ms - ------------------------------------------------------------ - GROUP "scrollingQuirksIframeVert" has 1 test to run - _AssertFailure: assertEqual() failed: - expected - EQUAL - but got - abs1.offsetTop=36 control.offsetTop=54 - - ERROR IN: function... - FAILED test: ../../dojo/tests/_base/html.html::scrollingQuirksIframeVert::test_scrollingQuirksIframeVert x ms - ------------------------------------------------------------ - GROUP "scrollingStrictIframeVert" has 1 test to run - _AssertFailure: assertEqual() failed: - expected - EQUAL - but got - abs1.offsetTop=36 control.offsetTop=54 - - ERROR IN: function... - FAILED test: ../../dojo/tests/_base/html.html::scrollingStrictIframeVert::test_scrollingStrictIframeVert x ms - ------------------------------------------------------------ - GROUP "scrollingQuirksIframeBoth" has 1 test to run - _AssertFailure: assertEqual() failed: - expected - EQUAL - but got - abs1.offsetTop=36 control.offsetTop=54 - - ERROR IN: function... - FAILED test: ../../dojo/tests/_base/html.html::scrollingQuirksIframeBoth::test_scrollingQuirksIframeBoth x ms - ------------------------------------------------------------ - GROUP "scrollingStrictIframeBoth" has 1 test to run - _AssertFailure: assertEqual() failed: - expected - EQUAL - but got - abs1.offsetTop=36 control.offsetTop=54 - - ERROR IN: function... - FAILED test: ../../dojo/tests/_base/html.html::scrollingStrictIframeBoth::test_scrollingStrictIframeBoth x ms - PASSED test: ../../dojo/tests/_base/html.html x ms - ------------------------------------------------------------ - GROUP "tests._base.html_id" has 1 test to run - 1 tests to run in 1 groups - ------------------------------------------------------------ - GROUP "t" has 1 test to run - PASSED test: ../../dojo/tests/_base/html_id.html::t::byId x ms - PASSED test: ../../dojo/tests/_base/html_id.html x ms - ------------------------------------------------------------ - GROUP "tests._base.html_element" has 1 test to run - 21 tests to run in 1 groups - ------------------------------------------------------------ - GROUP "t" has 21 tests to run - PASSED test: ../../dojo/tests/_base/html_element.html::t::createBasic x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::createAttrs x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::createPlace x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::createHtml x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::createPlaceRef x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::destroyList x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::createList x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::destroyAll x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::recreateOneV1 x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::recreateOneV2 x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::emptyDiv x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::emptyTable x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::toDomSpans x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::toDomTr x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::toDomText x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::toDomOption x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::placeDivs x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::placeTable x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::placeReplace x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::placeOnly x ms - PASSED test: ../../dojo/tests/_base/html_element.html::t::placeNumber x ms - PASSED test: ../../dojo/tests/_base/html_element.html x ms - ------------------------------------------------------------ - GROUP "tests._base.html_rtl" has 1 test to run - 19 tests to run in 17 groups - ------------------------------------------------------------ - GROUP "rtl" has 3 tests to run - PASSED test: ../../dojo/tests/_base/html_rtl.html::rtl::coordsWithScrolling x ms - PASSED test: ../../dojo/tests/_base/html_rtl.html::rtl::eventClientXY_IE x ms - _AssertFailure: assertEqual() failed: - expected - EQUAL - but got - abs1.offsetTop=1221 control.offsetTop=1239 - - ERROR IN: function... - FAILED test: ../../dojo/tests/_base/html_rtl.html::rtl::testScrolledPosition x ms - ------------------------------------------------------------ - GROUP "scrollingQuirksIframeNoneSmall" has 1 test to run - _AssertFailure: assertEqual() failed: - expected - EQUAL - but got - abs1.offsetTop=36 control.offsetTop=54 - - ERROR IN: function... - FAILED test: ../../dojo/tests/_base/html_rtl.html::scrollingQuirksIframeNoneSmall::test_scrollingQuirksIframeNoneSmall x ms - ------------------------------------------------------------ - GROUP "scrollingQuirksIframeNoneLarge" has 1 test to run - _AssertFailure: assertEqual() failed: - expected - EQUAL - but got - abs1.offsetTop=36 control.offsetTop=54 - - ERROR IN: function... - FAILED test: ../../dojo/tests/_base/html_rtl.html::scrollingQuirksIframeNoneLarge::test_scrollingQuirksIframeNoneLarge x ms - ------------------------------------------------------------ - GROUP "scrollingStrictIframeNoneSmall" has 1 test to run - _AssertFailure: assertEqual() failed: - expected - EQUAL - but got - abs1.offsetTop=36 control.offsetTop=54 - - ERROR IN: function... - FAILED test: ../../dojo/tests/_base/html_rtl.html::scrollingStrictIframeNoneSmall::test_scrollingStrictIframeNoneSmall x ms - ------------------------------------------------------------ - GROUP "scrollingStrictIframeNoneLarge" has 1 test to run - _AssertFailure: assertEqual() failed: - expected - EQUAL - but got - abs1.offsetTop=36 control.offsetTop=54 - - ERROR IN: function... - FAILED test: ../../dojo/tests/_base/html_rtl.html::scrollingStrictIframeNoneLarge::test_scrollingStrictIframeNoneLarge x ms - ------------------------------------------------------------ - GROUP "scrollingQuirksIframeHorzSmall" has 1 test to run - _AssertFailure: assertEqual() failed: - expected - EQUAL - but got - abs1.offsetTop=36 control.offsetTop=54 - - ERROR IN: function... - FAILED test: ../../dojo/tests/_base/html_rtl.html::scrollingQuirksIframeHorzSmall::test_scrollingQuirksIframeHorzSmall x ms - ------------------------------------------------------------ - GROUP "scrollingQuirksIframeHorzLarge" has 1 test to run - _AssertFailure: assertEqual() failed: - expected - EQUAL - but got - abs1.offsetTop=36 control.offsetTop=54 - - ERROR IN: function... - FAILED test: ../../dojo/tests/_base/html_rtl.html::scrollingQuirksIframeHorzLarge::test_scrollingQuirksIframeHorzLarge x ms - ------------------------------------------------------------ - GROUP "scrollingStrictIframeHorzSmall" has 1 test to run - _AssertFailure: assertEqual() failed: - expected - EQUAL - but got - abs1.offsetTop=36 control.offsetTop=54 - - ERROR IN: function... - FAILED test: ../../dojo/tests/_base/html_rtl.html::scrollingStrictIframeHorzSmall::test_scrollingStrictIframeHorzSmall x ms - ------------------------------------------------------------ - GROUP "scrollingStrictIframeHorzLarge" has 1 test to run - _AssertFailure: assertEqual() failed: - expected - EQUAL - but got - abs1.offsetTop=36 control.offsetTop=54 - - ERROR IN: function... - FAILED test: ../../dojo/tests/_base/html_rtl.html::scrollingStrictIframeHorzLarge::test_scrollingStrictIframeHorzLarge x ms - ------------------------------------------------------------ - GROUP "scrollingQuirksIframeVertSmall" has 1 test to run - _AssertFailure: assertEqual() failed: - expected - EQUAL - but got - abs1.offsetTop=36 control.offsetTop=54 - - ERROR IN: function... - FAILED test: ../../dojo/tests/_base/html_rtl.html::scrollingQuirksIframeVertSmall::test_scrollingQuirksIframeVertSmall x ms - ------------------------------------------------------------ - GROUP "scrollingQuirksIframeVertLarge" has 1 test to run - _AssertFailure: assertEqual() failed: - expected - EQUAL - but got - abs1.offsetTop=36 control.offsetTop=54 - - ERROR IN: function... - FAILED test: ../../dojo/tests/_base/html_rtl.html::scrollingQuirksIframeVertLarge::test_scrollingQuirksIframeVertLarge x ms - ------------------------------------------------------------ - GROUP "scrollingStrictIframeVertSmall" has 1 test to run - _AssertFailure: assertEqual() failed: - expected - EQUAL - but got - abs1.offsetTop=36 control.offsetTop=54 - - ERROR IN: function... - FAILED test: ../../dojo/tests/_base/html_rtl.html::scrollingStrictIframeVertSmall::test_scrollingStrictIframeVertSmall x ms - ------------------------------------------------------------ - GROUP "scrollingStrictIframeVertLarge" has 1 test to run - _AssertFailure: assertEqual() failed: - expected - EQUAL - but got - abs1.offsetTop=36 control.offsetTop=54 - - ERROR IN: function... - FAILED test: ../../dojo/tests/_base/html_rtl.html::scrollingStrictIframeVertLarge::test_scrollingStrictIframeVertLarge x ms - ------------------------------------------------------------ - GROUP "scrollingQuirksIframeBothSmall" has 1 test to run - _AssertFailure: assertEqual() failed: - expected - EQUAL - but got - abs1.offsetTop=36 control.offsetTop=54 - - ERROR IN: function... - FAILED test: ../../dojo/tests/_base/html_rtl.html::scrollingQuirksIframeBothSmall::test_scrollingQuirksIframeBothSmall x ms - ------------------------------------------------------------ - GROUP "scrollingQuirksIframeBothLarge" has 1 test to run - _AssertFailure: assertEqual() failed: - expected - EQUAL - but got - abs1.offsetTop=36 control.offsetTop=54 - - ERROR IN: function... - FAILED test: ../../dojo/tests/_base/html_rtl.html::scrollingQuirksIframeBothLarge::test_scrollingQuirksIframeBothLarge x ms - ------------------------------------------------------------ - GROUP "scrollingStrictIframeBothSmall" has 1 test to run - _AssertFailure: assertEqual() failed: - expected - EQUAL - but got - abs1.offsetTop=36 control.offsetTop=54 - - ERROR IN: function... - FAILED test: ../../dojo/tests/_base/html_rtl.html::scrollingStrictIframeBothSmall::test_scrollingStrictIframeBothSmall x ms - ------------------------------------------------------------ - GROUP "scrollingStrictIframeBothLarge" has 1 test to run - _AssertFailure: assertEqual() failed: - expected - EQUAL - but got - abs1.offsetTop=36 control.offsetTop=54 - - ERROR IN: function... - FAILED test: ../../dojo/tests/_base/html_rtl.html::scrollingStrictIframeBothLarge::test_scrollingStrictIframeBothLarge x ms - PASSED test: ../../dojo/tests/_base/html_rtl.html x ms - ------------------------------------------------------------ - GROUP "tests._base.html_quirks" has 1 test to run - 39 tests to run in 1 groups - ------------------------------------------------------------ - GROUP "t" has 39 tests to run - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(100, dojo.marginBox('sq100').w); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(100, dojo.marginBox('sq100').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(120, dojo.marginBox('sq100margin10').w); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(120, dojo.marginBox('sq100margin10').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(100, dojo.contentBox('sq100margin10').w); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(100, dojo.contentBox('sq100margin10').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(100, dojo.marginBox('sq100nopos').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::coordsBasic x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::coordsMargin x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::coordsBorder x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::sq100nopos x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(140, dojo.marginBox('sq100margin10pad10').w); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(140, dojo.marginBox('sq100margin10pad10').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(120, dojo.marginBox('sq100pad10').w); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(120, dojo.marginBox('sq100pad10').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(110, dojo.marginBox('sq100ltpad10').w); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(110, dojo.marginBox('sq100ltpad10').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(100, dojo.contentBox('sq100ltpad10').w); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(100, dojo.contentBox('sq100ltpad10').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(120, dojo.marginBox('sq100ltpad10rbmargin10').w); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(120, dojo.marginBox('sq100ltpad10rbmargin10').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(120, dojo.marginBox('sq100border10').w); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(120, dojo.marginBox('sq100border10').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(100, dojo.contentBox('sq100border10').w); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(100, dojo.contentBox('sq100border10').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(140, dojo.marginBox('sq100border10margin10').w); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(140, dojo.marginBox('sq100border10margin10').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(100, dojo.contentBox('sq100border10margin10').w); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(100, dojo.contentBox('sq100border10margin10').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(160, dojo.marginBox('sq100border10margin10pad10').w); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(160, dojo.marginBox('sq100border10margin10pad10').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(100, dojo.contentBox('sq100border10margin10pad10').w); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::t.is(100, dojo.contentBox('sq100border10margin10pad10').h); x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::emptySvg x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::destroySvg x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::emptyObject x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::destroyObject x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::destroyIframe x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html::t::destroyDivNotInDOM x ms - PASSED test: ../../dojo/tests/_base/html_quirks.html x ms - ------------------------------------------------------------ - GROUP "tests._base.html_box" has 1 test to run - 6 tests to run in 1 groups - ------------------------------------------------------------ - GROUP "t" has 6 tests to run - PASSED test: ../../dojo/tests/_base/html_box.html::t::reciprocalTests x ms - PASSED test: ../../dojo/tests/_base/html_box.html::t::fitTests x ms - PASSED test: ../../dojo/tests/_base/html_box.html::t::fitTestsOverflow x ms - PASSED test: ../../dojo/tests/_base/html_box.html::t::fitTestsFloat x ms - PASSED test: ../../dojo/tests/_base/html_box.html::t::reciprocalTestsInline x ms - PASSED test: ../../dojo/tests/_base/html_box.html::t::reciprocalTestsButtonChild x ms - PASSED test: ../../dojo/tests/_base/html_box.html x ms - ------------------------------------------------------------ - GROUP "tests._base.html_box_quirks" has 1 test to run - 6 tests to run in 1 groups - ------------------------------------------------------------ - GROUP "t" has 6 tests to run - PASSED test: ../../dojo/tests/_base/html_box_quirks.html::t::reciprocalTests x ms - PASSED test: ../../dojo/tests/_base/html_box_quirks.html::t::fitTests x ms - PASSED test: ../../dojo/tests/_base/html_box_quirks.html::t::fitTestsOverflow x ms - PASSED test: ../../dojo/tests/_base/html_box_quirks.html::t::fitTestsFloat x ms - PASSED test: ../../dojo/tests/_base/html_box_quirks.html::t::reciprocalTestsInline x ms - PASSED test: ../../dojo/tests/_base/html_box_quirks.html::t::reciprocalTestsButtonChild x ms - PASSED test: ../../dojo/tests/_base/html_box_quirks.html x ms - ------------------------------------------------------------ - GROUP "tests._base.html_isBodyLtr" has 1 test to run - 5 tests to run in 1 groups - ------------------------------------------------------------ - GROUP "t" has 5 tests to run - PASSED test: ../../dojo/tests/_base/html_isBodyLtr.html::t::testRtl x ms - PASSED test: ../../dojo/tests/_base/html_isBodyLtr.html::t::testCache x ms - PASSED test: ../../dojo/tests/_base/html_isBodyLtr.html::t::testHtmlValue x ms - PASSED test: ../../dojo/tests/_base/html_isBodyLtr.html::t::testDefaultValue x ms - PASSED test: ../../dojo/tests/_base/html_isBodyLtr.html::t::testHiddenIframe x ms - PASSED test: ../../dojo/tests/_base/html_isBodyLtr.html x ms - ------------------------------------------------------------ - GROUP "tests._base.html_docScroll" has 1 test to run - 4 tests to run in 1 groups - ------------------------------------------------------------ - GROUP "t" has 4 tests to run - PASSED test: ../../dojo/tests/_base/html_docScroll.html::t::testNonScrolled x ms - _AssertFailure: assertEqual() failed: - expected - 1 - but got - 0 - - ERROR IN: function... - FAILED test: ../../dojo/tests/_base/html_docScroll.html::t::testScrolled x ms - _AssertFailure: assertEqual() failed: - expected - 1 - but got - 0 - - ERROR IN: function... - FAILED test: ../../dojo/tests/_base/html_docScroll.html::t::testQuirksNonScrolled x ms - _AssertFailure: assertEqual() failed: - expected - 10 - but got - 0 - - ERROR IN: function... - FAILED test: ../../dojo/tests/_base/html_docScroll.html::t::testQuirksScrolled x ms - PASSED test: ../../dojo/tests/_base/html_docScroll.html x ms - ------------------------------------------------------------ - | TEST SUMMARY: - ------------------------------------------------------------ - 213 tests in 9 groups - 0 errors - 28 failures diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/ajax-header.js b/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/ajax-header.js deleted file mode 100644 index 5c6221bf6c1..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/ajax-header.js +++ /dev/null @@ -1,7 +0,0 @@ -htmx.defineExtension('ajax-header', { - onEvent: function (name, evt) { - if (name === "htmx:configRequest") { - evt.detail.headers['X-Requested-With'] = 'XMLHttpRequest'; - } - } -}); \ No newline at end of file diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/alpine-morph.js b/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/alpine-morph.js deleted file mode 100644 index 1872daec725..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/alpine-morph.js +++ /dev/null @@ -1,16 +0,0 @@ -htmx.defineExtension('alpine-morph', { - isInlineSwap: function (swapStyle) { - return swapStyle === 'morph'; - }, - handleSwap: function (swapStyle, target, fragment) { - if (swapStyle === 'morph') { - if (fragment.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { - Alpine.morph(target, fragment.firstElementChild); - return [target]; - } else { - Alpine.morph(target, fragment.outerHTML); - return [target]; - } - } - } -}); \ No newline at end of file diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/class-tools.js b/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/class-tools.js deleted file mode 100644 index 1cf4b426907..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/class-tools.js +++ /dev/null @@ -1,92 +0,0 @@ -(function () { - - function splitOnWhitespace(trigger) { - return trigger.split(/\s+/); - } - - function parseClassOperation(trimmedValue) { - var split = splitOnWhitespace(trimmedValue); - if (split.length > 1) { - var operation = split[0]; - var classDef = split[1].trim(); - var cssClass; - var delay; - if (classDef.indexOf(":") > 0) { - var splitCssClass = classDef.split(':'); - cssClass = splitCssClass[0]; - delay = htmx.parseInterval(splitCssClass[1]); - } else { - cssClass = classDef; - delay = 100; - } - return { - operation: operation, - cssClass: cssClass, - delay: delay - } - } else { - return null; - } - } - - function performOperation(elt, classOperation, classList, currentRunTime) { - setTimeout(function () { - elt.classList[classOperation.operation].call(elt.classList, classOperation.cssClass); - }, currentRunTime) - } - - function toggleOperation(elt, classOperation, classList, currentRunTime) { - setTimeout(function () { - setInterval(function () { - elt.classList[classOperation.operation].call(elt.classList, classOperation.cssClass); - }, classOperation.delay); - }, currentRunTime) - } - - function processClassList(elt, classList) { - var runs = classList.split("&"); - for (var i = 0; i < runs.length; i++) { - var run = runs[i]; - var currentRunTime = 0; - var classOperations = run.split(","); - for (var j = 0; j < classOperations.length; j++) { - var value = classOperations[j]; - var trimmedValue = value.trim(); - var classOperation = parseClassOperation(trimmedValue); - if (classOperation) { - if (classOperation.operation === "toggle") { - toggleOperation(elt, classOperation, classList, currentRunTime); - currentRunTime = currentRunTime + classOperation.delay; - } else { - currentRunTime = currentRunTime + classOperation.delay; - performOperation(elt, classOperation, classList, currentRunTime); - } - } - } - } - } - - function maybeProcessClasses(elt) { - if (elt.getAttribute) { - var classList = elt.getAttribute("classes") || elt.getAttribute("data-classes"); - if (classList) { - processClassList(elt, classList); - } - } - } - - htmx.defineExtension('class-tools', { - onEvent: function (name, evt) { - if (name === "htmx:afterProcessNode") { - var elt = evt.detail.elt; - maybeProcessClasses(elt); - if (elt.querySelectorAll) { - var children = elt.querySelectorAll("[classes], [data-classes]"); - for (var i = 0; i < children.length; i++) { - maybeProcessClasses(children[i]); - } - } - } - } - }); -})(); \ No newline at end of file diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/client-side-templates.js b/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/client-side-templates.js deleted file mode 100644 index 2bace4192d7..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/client-side-templates.js +++ /dev/null @@ -1,96 +0,0 @@ -htmx.defineExtension('client-side-templates', { - transformResponse : function(text, xhr, elt) { - - var mustacheTemplate = htmx.closest(elt, "[mustache-template]"); - if (mustacheTemplate) { - var data = JSON.parse(text); - var templateId = mustacheTemplate.getAttribute('mustache-template'); - var template = htmx.find("#" + templateId); - if (template) { - return Mustache.render(template.innerHTML, data); - } else { - throw "Unknown mustache template: " + templateId; - } - } - - var mustacheArrayTemplate = htmx.closest(elt, "[mustache-array-template]"); - if (mustacheArrayTemplate) { - var data = JSON.parse(text); - var templateId = mustacheArrayTemplate.getAttribute('mustache-array-template'); - var template = htmx.find("#" + templateId); - if (template) { - return Mustache.render(template.innerHTML, {"data": data }); - } else { - throw "Unknown mustache template: " + templateId; - } - } - - var handlebarsTemplate = htmx.closest(elt, "[handlebars-template]"); - if (handlebarsTemplate) { - var data = JSON.parse(text); - var templateId = handlebarsTemplate.getAttribute('handlebars-template'); - var templateElement = htmx.find('#' + templateId).innerHTML; - var renderTemplate = Handlebars.compile(templateElement); - if (renderTemplate) { - return renderTemplate(data); - } else { - throw "Unknown handlebars template: " + templateId; - } - } - - var handlebarsArrayTemplate = htmx.closest(elt, "[handlebars-array-template]"); - if (handlebarsArrayTemplate) { - var data = JSON.parse(text); - var templateId = handlebarsArrayTemplate.getAttribute('handlebars-array-template'); - var templateElement = htmx.find('#' + templateId).innerHTML; - var renderTemplate = Handlebars.compile(templateElement); - if (renderTemplate) { - return renderTemplate(data); - } else { - throw "Unknown handlebars template: " + templateId; - } - } - - var nunjucksTemplate = htmx.closest(elt, "[nunjucks-template]"); - if (nunjucksTemplate) { - var data = JSON.parse(text); - var templateName = nunjucksTemplate.getAttribute('nunjucks-template'); - var template = htmx.find('#' + templateName); - if (template) { - return nunjucks.renderString(template.innerHTML, data); - } else { - return nunjucks.render(templateName, data); - } - } - - var xsltTemplate = htmx.closest(elt, "[xslt-template]"); - if (xsltTemplate) { - var templateId = xsltTemplate.getAttribute('xslt-template'); - var template = htmx.find("#" + templateId); - if (template) { - var content = template.innerHTML ? new DOMParser().parseFromString(template.innerHTML, 'application/xml') - : template.contentDocument; - var processor = new XSLTProcessor(); - processor.importStylesheet(content); - var data = new DOMParser().parseFromString(text, "application/xml"); - var frag = processor.transformToFragment(data, document); - return new XMLSerializer().serializeToString(frag); - } else { - throw "Unknown XSLT template: " + templateId; - } - } - - var nunjucksArrayTemplate = htmx.closest(elt, "[nunjucks-array-template]"); - if (nunjucksArrayTemplate) { - var data = JSON.parse(text); - var templateName = nunjucksArrayTemplate.getAttribute('nunjucks-array-template'); - var template = htmx.find('#' + templateName); - if (template) { - return nunjucks.renderString(template.innerHTML, {"data": data}); - } else { - return nunjucks.render(templateName, {"data": data}); - } - } - return text; - } -}); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/debug.js b/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/debug.js deleted file mode 100644 index 861ee743cb9..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/debug.js +++ /dev/null @@ -1,11 +0,0 @@ -htmx.defineExtension('debug', { - onEvent: function (name, evt) { - if (console.debug) { - console.debug(name, evt); - } else if (console) { - console.log("DEBUG:", name, evt); - } else { - throw "NO CONSOLE SUPPORTED" - } - } -}); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/disable-element.js b/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/disable-element.js deleted file mode 100644 index 07bef62d80e..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/disable-element.js +++ /dev/null @@ -1,18 +0,0 @@ -"use strict"; - -// Disable Submit Button -htmx.defineExtension('disable-element', { - onEvent: function (name, evt) { - let elt = evt.detail.elt; - let target = elt.getAttribute("hx-disable-element"); - let targetElements = (target == "self") ? [ elt ] : document.querySelectorAll(target); - - for (var i = 0; i < targetElements.length; i++) { - if (name === "htmx:beforeRequest" && targetElements[i]) { - targetElements[i].disabled = true; - } else if (name == "htmx:afterRequest" && targetElements[i]) { - targetElements[i].disabled = false; - } - } - } -}); \ No newline at end of file diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/event-header.js b/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/event-header.js deleted file mode 100644 index c7d29334e9e..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/event-header.js +++ /dev/null @@ -1,37 +0,0 @@ -(function(){ - function stringifyEvent(event) { - var obj = {}; - for (var key in event) { - obj[key] = event[key]; - } - return JSON.stringify(obj, function(key, value){ - if(value instanceof Node){ - var nodeRep = value.tagName; - if (nodeRep) { - nodeRep = nodeRep.toLowerCase(); - if(value.id){ - nodeRep += "#" + value.id; - } - if(value.classList && value.classList.length){ - nodeRep += "." + value.classList.toString().replace(" ", ".") - } - return nodeRep; - } else { - return "Node" - } - } - if (value instanceof Window) return 'Window'; - return value; - }); - } - - htmx.defineExtension('event-header', { - onEvent: function (name, evt) { - if (name === "htmx:configRequest") { - if (evt.detail.triggeringEvent) { - evt.detail.headers['Triggering-Event'] = stringifyEvent(evt.detail.triggeringEvent); - } - } - } - }); -})(); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/head-support.js b/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/head-support.js deleted file mode 100644 index 67cfc6924ba..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/head-support.js +++ /dev/null @@ -1,141 +0,0 @@ -//========================================================== -// head-support.js -// -// An extension to htmx 1.0 to add head tag merging. -//========================================================== -(function(){ - - var api = null; - - function log() { - //console.log(arguments); - } - - function mergeHead(newContent, defaultMergeStrategy) { - - if (newContent && newContent.indexOf(' -1) { - const htmlDoc = document.createElement("html"); - // remove svgs to avoid conflicts - var contentWithSvgsRemoved = newContent.replace(/]*>|>)([\s\S]*?)<\/svg>/gim, ''); - // extract head tag - var headTag = contentWithSvgsRemoved.match(/(]*>|>)([\s\S]*?)<\/head>)/im); - - // if the head tag exists... - if (headTag) { - - var added = [] - var removed = [] - var preserved = [] - var nodesToAppend = [] - - htmlDoc.innerHTML = headTag; - var newHeadTag = htmlDoc.querySelector("head"); - var currentHead = document.head; - - if (newHeadTag == null) { - return; - } else { - // put all new head elements into a Map, by their outerHTML - var srcToNewHeadNodes = new Map(); - for (const newHeadChild of newHeadTag.children) { - srcToNewHeadNodes.set(newHeadChild.outerHTML, newHeadChild); - } - } - - - - // determine merge strategy - var mergeStrategy = api.getAttributeValue(newHeadTag, "hx-head") || defaultMergeStrategy; - - // get the current head - for (const currentHeadElt of currentHead.children) { - - // If the current head element is in the map - var inNewContent = srcToNewHeadNodes.has(currentHeadElt.outerHTML); - var isReAppended = currentHeadElt.getAttribute("hx-head") === "re-eval"; - var isPreserved = api.getAttributeValue(currentHeadElt, "hx-preserve") === "true"; - if (inNewContent || isPreserved) { - if (isReAppended) { - // remove the current version and let the new version replace it and re-execute - removed.push(currentHeadElt); - } else { - // this element already exists and should not be re-appended, so remove it from - // the new content map, preserving it in the DOM - srcToNewHeadNodes.delete(currentHeadElt.outerHTML); - preserved.push(currentHeadElt); - } - } else { - if (mergeStrategy === "append") { - // we are appending and this existing element is not new content - // so if and only if it is marked for re-append do we do anything - if (isReAppended) { - removed.push(currentHeadElt); - nodesToAppend.push(currentHeadElt); - } - } else { - // if this is a merge, we remove this content since it is not in the new head - if (api.triggerEvent(document.body, "htmx:removingHeadElement", {headElement: currentHeadElt}) !== false) { - removed.push(currentHeadElt); - } - } - } - } - - // Push the tremaining new head elements in the Map into the - // nodes to append to the head tag - nodesToAppend.push(...srcToNewHeadNodes.values()); - log("to append: ", nodesToAppend); - - for (const newNode of nodesToAppend) { - log("adding: ", newNode); - var newElt = document.createRange().createContextualFragment(newNode.outerHTML); - log(newElt); - if (api.triggerEvent(document.body, "htmx:addingHeadElement", {headElement: newElt}) !== false) { - currentHead.appendChild(newElt); - added.push(newElt); - } - } - - // remove all removed elements, after we have appended the new elements to avoid - // additional network requests for things like style sheets - for (const removedElement of removed) { - if (api.triggerEvent(document.body, "htmx:removingHeadElement", {headElement: removedElement}) !== false) { - currentHead.removeChild(removedElement); - } - } - - api.triggerEvent(document.body, "htmx:afterHeadMerge", {added: added, kept: preserved, removed: removed}); - } - } - } - - htmx.defineExtension("head-support", { - init: function(apiRef) { - // store a reference to the internal API. - api = apiRef; - - htmx.on('htmx:afterSwap', function(evt){ - var serverResponse = evt.detail.xhr.response; - if (api.triggerEvent(document.body, "htmx:beforeHeadMerge", evt.detail)) { - mergeHead(serverResponse, evt.detail.boosted ? "merge" : "append"); - } - }) - - htmx.on('htmx:historyRestore', function(evt){ - if (api.triggerEvent(document.body, "htmx:beforeHeadMerge", evt.detail)) { - if (evt.detail.cacheMiss) { - mergeHead(evt.detail.serverResponse, "merge"); - } else { - mergeHead(evt.detail.item.head, "merge"); - } - } - }) - - htmx.on('htmx:historyItemCreated', function(evt){ - var historyItem = evt.detail.item; - historyItem.head = document.head.outerHTML; - }) - } - }); - -})() \ No newline at end of file diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/include-vals.js b/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/include-vals.js deleted file mode 100644 index d8f5ce4fa72..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/include-vals.js +++ /dev/null @@ -1,24 +0,0 @@ -(function(){ - - function mergeObjects(obj1, obj2) { - for (var key in obj2) { - if (obj2.hasOwnProperty(key)) { - obj1[key] = obj2[key]; - } - } - return obj1; - } - - htmx.defineExtension('include-vals', { - onEvent: function (name, evt) { - if (name === "htmx:configRequest") { - var includeValsElt = htmx.closest(evt.detail.elt, "[include-vals],[data-include-vals]"); - if (includeValsElt) { - var includeVals = includeValsElt.getAttribute("include-vals") || includeValsElt.getAttribute("data-include-vals"); - var valuesToInclude = eval("({" + includeVals + "})"); - mergeObjects(evt.detail.parameters, valuesToInclude); - } - } - } - }); -})(); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/json-enc.js b/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/json-enc.js deleted file mode 100644 index db0aa36f215..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/json-enc.js +++ /dev/null @@ -1,12 +0,0 @@ -htmx.defineExtension('json-enc', { - onEvent: function (name, evt) { - if (name === "htmx:configRequest") { - evt.detail.headers['Content-Type'] = "application/json"; - } - }, - - encodeParameters : function(xhr, parameters, elt) { - xhr.overrideMimeType('text/json'); - return (JSON.stringify(parameters)); - } -}); \ No newline at end of file diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/loading-states.js b/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/loading-states.js deleted file mode 100644 index c8ab51da3c5..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/loading-states.js +++ /dev/null @@ -1,183 +0,0 @@ -;(function () { - let loadingStatesUndoQueue = [] - - function loadingStateContainer(target) { - return htmx.closest(target, '[data-loading-states]') || document.body - } - - function mayProcessUndoCallback(target, callback) { - if (document.body.contains(target)) { - callback() - } - } - - function mayProcessLoadingStateByPath(elt, requestPath) { - const pathElt = htmx.closest(elt, '[data-loading-path]') - if (!pathElt) { - return true - } - - return pathElt.getAttribute('data-loading-path') === requestPath - } - - function queueLoadingState(sourceElt, targetElt, doCallback, undoCallback) { - const delayElt = htmx.closest(sourceElt, '[data-loading-delay]') - if (delayElt) { - const delayInMilliseconds = - delayElt.getAttribute('data-loading-delay') || 200 - const timeout = setTimeout(function () { - doCallback() - - loadingStatesUndoQueue.push(function () { - mayProcessUndoCallback(targetElt, undoCallback) - }) - }, delayInMilliseconds) - - loadingStatesUndoQueue.push(function () { - mayProcessUndoCallback(targetElt, function () { clearTimeout(timeout) }) - }) - } else { - doCallback() - loadingStatesUndoQueue.push(function () { - mayProcessUndoCallback(targetElt, undoCallback) - }) - } - } - - function getLoadingStateElts(loadingScope, type, path) { - return Array.from(htmx.findAll(loadingScope, "[" + type + "]")).filter( - function (elt) { return mayProcessLoadingStateByPath(elt, path) } - ) - } - - function getLoadingTarget(elt) { - if (elt.getAttribute('data-loading-target')) { - return Array.from( - htmx.findAll(elt.getAttribute('data-loading-target')) - ) - } - return [elt] - } - - htmx.defineExtension('loading-states', { - onEvent: function (name, evt) { - if (name === 'htmx:beforeRequest') { - const container = loadingStateContainer(evt.target) - - const loadingStateTypes = [ - 'data-loading', - 'data-loading-class', - 'data-loading-class-remove', - 'data-loading-disable', - 'data-loading-aria-busy', - ] - - let loadingStateEltsByType = {} - - loadingStateTypes.forEach(function (type) { - loadingStateEltsByType[type] = getLoadingStateElts( - container, - type, - evt.detail.pathInfo.requestPath - ) - }) - - loadingStateEltsByType['data-loading'].forEach(function (sourceElt) { - getLoadingTarget(sourceElt).forEach(function (targetElt) { - queueLoadingState( - sourceElt, - targetElt, - function () { - targetElt.style.display = - sourceElt.getAttribute('data-loading') || - 'inline-block' }, - function () { targetElt.style.display = 'none' } - ) - }) - }) - - loadingStateEltsByType['data-loading-class'].forEach( - function (sourceElt) { - const classNames = sourceElt - .getAttribute('data-loading-class') - .split(' ') - - getLoadingTarget(sourceElt).forEach(function (targetElt) { - queueLoadingState( - sourceElt, - targetElt, - function () { - classNames.forEach(function (className) { - targetElt.classList.add(className) - }) - }, - function() { - classNames.forEach(function (className) { - targetElt.classList.remove(className) - }) - } - ) - }) - } - ) - - loadingStateEltsByType['data-loading-class-remove'].forEach( - function (sourceElt) { - const classNames = sourceElt - .getAttribute('data-loading-class-remove') - .split(' ') - - getLoadingTarget(sourceElt).forEach(function (targetElt) { - queueLoadingState( - sourceElt, - targetElt, - function () { - classNames.forEach(function (className) { - targetElt.classList.remove(className) - }) - }, - function() { - classNames.forEach(function (className) { - targetElt.classList.add(className) - }) - } - ) - }) - } - ) - - loadingStateEltsByType['data-loading-disable'].forEach( - function (sourceElt) { - getLoadingTarget(sourceElt).forEach(function (targetElt) { - queueLoadingState( - sourceElt, - targetElt, - function() { targetElt.disabled = true }, - function() { targetElt.disabled = false } - ) - }) - } - ) - - loadingStateEltsByType['data-loading-aria-busy'].forEach( - function (sourceElt) { - getLoadingTarget(sourceElt).forEach(function (targetElt) { - queueLoadingState( - sourceElt, - targetElt, - function () { targetElt.setAttribute("aria-busy", "true") }, - function () { targetElt.removeAttribute("aria-busy") } - ) - }) - } - ) - } - - if (name === 'htmx:beforeOnLoad') { - while (loadingStatesUndoQueue.length > 0) { - loadingStatesUndoQueue.shift()() - } - } - }, - }) -})() diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/method-override.js b/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/method-override.js deleted file mode 100644 index 2e3504cb04e..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/method-override.js +++ /dev/null @@ -1,11 +0,0 @@ -htmx.defineExtension('method-override', { - onEvent: function (name, evt) { - if (name === "htmx:configRequest") { - var method = evt.detail.verb; - if (method !== "get" || method !== "post") { - evt.detail.headers['X-HTTP-Method-Override'] = method.toUpperCase(); - evt.detail.verb = "post"; - } - } - } -}); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/morphdom-swap.js b/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/morphdom-swap.js deleted file mode 100644 index a1e53ce907a..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/morphdom-swap.js +++ /dev/null @@ -1,17 +0,0 @@ -htmx.defineExtension('morphdom-swap', { - isInlineSwap: function(swapStyle) { - return swapStyle === 'morphdom'; - }, - handleSwap: function (swapStyle, target, fragment) { - if (swapStyle === 'morphdom') { - if (fragment.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { - // IE11 doesn't support DocumentFragment.firstElementChild - morphdom(target, fragment.firstElementChild || fragment.firstChild); - return [target]; - } else { - morphdom(target, fragment.outerHTML); - return [target]; - } - } - } -}); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/multi-swap.js b/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/multi-swap.js deleted file mode 100644 index f38f5b0655e..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/multi-swap.js +++ /dev/null @@ -1,45 +0,0 @@ -(function () { - - /** @type {import("../htmx").HtmxInternalApi} */ - var api; - - htmx.defineExtension('multi-swap', { - init: function (apiRef) { - api = apiRef; - }, - isInlineSwap: function (swapStyle) { - return swapStyle.indexOf('multi:') === 0; - }, - handleSwap: function (swapStyle, target, fragment, settleInfo) { - if (swapStyle.indexOf('multi:') === 0) { - var selectorToSwapStyle = {}; - var elements = swapStyle.replace(/^multi\s*:\s*/, '').split(/\s*,\s*/); - - elements.map(function (element) { - var split = element.split(/\s*:\s*/); - var elementSelector = split[0]; - var elementSwapStyle = typeof (split[1]) !== "undefined" ? split[1] : "innerHTML"; - - if (elementSelector.charAt(0) !== '#') { - console.error("HTMX multi-swap: unsupported selector '" + elementSelector + "'. Only ID selectors starting with '#' are supported."); - return; - } - - selectorToSwapStyle[elementSelector] = elementSwapStyle; - }); - - for (var selector in selectorToSwapStyle) { - var swapStyle = selectorToSwapStyle[selector]; - var elementToSwap = fragment.querySelector(selector); - if (elementToSwap) { - api.oobSwap(swapStyle, elementToSwap, settleInfo); - } else { - console.warn("HTMX multi-swap: selector '" + selector + "' not found in source content."); - } - } - - return true; - } - } - }); -})(); \ No newline at end of file diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/path-deps.js b/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/path-deps.js deleted file mode 100644 index 4987e50ebca..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/path-deps.js +++ /dev/null @@ -1,60 +0,0 @@ -(function(undefined){ - 'use strict'; - - // Save a reference to the global object (window in the browser) - var _root = this; - - function dependsOn(pathSpec, url) { - if (pathSpec === "ignore") { - return false; - } - var dependencyPath = pathSpec.split("/"); - var urlPath = url.split("/"); - for (var i = 0; i < urlPath.length; i++) { - var dependencyElement = dependencyPath.shift(); - var pathElement = urlPath[i]; - if (dependencyElement !== pathElement && dependencyElement !== "*") { - return false; - } - if (dependencyPath.length === 0 || (dependencyPath.length === 1 && dependencyPath[0] === "")) { - return true; - } - } - return false; - } - - function refreshPath(path) { - var eltsWithDeps = htmx.findAll("[path-deps]"); - for (var i = 0; i < eltsWithDeps.length; i++) { - var elt = eltsWithDeps[i]; - if (dependsOn(elt.getAttribute('path-deps'), path)) { - htmx.trigger(elt, "path-deps"); - } - } - } - - htmx.defineExtension('path-deps', { - onEvent: function (name, evt) { - if (name === "htmx:beforeOnLoad") { - var config = evt.detail.requestConfig; - // mutating call - if (config.verb !== "get" && evt.target.getAttribute('path-deps') !== 'ignore') { - refreshPath(config.path); - } - } - } - }); - - /** - * ******************** - * Expose functionality - * ******************** - */ - - _root.PathDeps = { - refresh: function(path) { - refreshPath(path); - } - }; - -}).call(this); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/path-params.js b/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/path-params.js deleted file mode 100644 index e251b8927d9..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/path-params.js +++ /dev/null @@ -1,11 +0,0 @@ -htmx.defineExtension('path-params', { - onEvent: function(name, evt) { - if (name === "htmx:configRequest") { - evt.detail.path = evt.detail.path.replace(/{([^}]+)}/g, function (_, param) { - var val = evt.detail.parameters[param]; - delete evt.detail.parameters[param]; - return val === undefined ? "{" + param + "}" : encodeURIComponent(val); - }) - } - } -}); \ No newline at end of file diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/preload.js b/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/preload.js deleted file mode 100644 index a7493703399..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/preload.js +++ /dev/null @@ -1,147 +0,0 @@ -// This adds the "preload" extension to htmx. By default, this will -// preload the targets of any tags with `href` or `hx-get` attributes -// if they also have a `preload` attribute as well. See documentation -// for more details -htmx.defineExtension("preload", { - - onEvent: function(name, event) { - - // Only take actions on "htmx:afterProcessNode" - if (name !== "htmx:afterProcessNode") { - return; - } - - // SOME HELPER FUNCTIONS WE'LL NEED ALONG THE WAY - - // attr gets the closest non-empty value from the attribute. - var attr = function(node, property) { - if (node == undefined) {return undefined;} - return node.getAttribute(property) || node.getAttribute("data-" + property) || attr(node.parentElement, property) - } - - // load handles the actual HTTP fetch, and uses htmx.ajax in cases where we're - // preloading an htmx resource (this sends the same HTTP headers as a regular htmx request) - var load = function(node) { - - // Called after a successful AJAX request, to mark the - // content as loaded (and prevent additional AJAX calls.) - var done = function(html) { - if (!node.preloadAlways) { - node.preloadState = "DONE" - } - - if (attr(node, "preload-images") == "true") { - document.createElement("div").innerHTML = html // create and populate a node to load linked resources, too. - } - } - - return function() { - - // If this value has already been loaded, then do not try again. - if (node.preloadState !== "READY") { - return; - } - - // Special handling for HX-GET - use built-in htmx.ajax function - // so that headers match other htmx requests, then set - // node.preloadState = TRUE so that requests are not duplicated - // in the future - var hxGet = node.getAttribute("hx-get") || node.getAttribute("data-hx-get") - if (hxGet) { - htmx.ajax("GET", hxGet, { - source: node, - handler:function(elt, info) { - done(info.xhr.responseText); - } - }); - return; - } - - // Otherwise, perform a standard xhr request, then set - // node.preloadState = TRUE so that requests are not duplicated - // in the future. - if (node.getAttribute("href")) { - var r = new XMLHttpRequest(); - r.open("GET", node.getAttribute("href")); - r.onload = function() {done(r.responseText);}; - r.send(); - return; - } - } - } - - // This function processes a specific node and sets up event handlers. - // We'll search for nodes and use it below. - var init = function(node) { - - // If this node DOES NOT include a "GET" transaction, then there's nothing to do here. - if (node.getAttribute("href") + node.getAttribute("hx-get") + node.getAttribute("data-hx-get") == "") { - return; - } - - // Guarantee that we only initialize each node once. - if (node.preloadState !== undefined) { - return; - } - - // Get event name from config. - var on = attr(node, "preload") || "mousedown" - const always = on.indexOf("always") !== -1 - if (always) { - on = on.replace('always', '').trim() - } - - // FALL THROUGH to here means we need to add an EventListener - - // Apply the listener to the node - node.addEventListener(on, function(evt) { - if (node.preloadState === "PAUSE") { // Only add one event listener - node.preloadState = "READY"; // Required for the `load` function to trigger - - // Special handling for "mouseover" events. Wait 100ms before triggering load. - if (on === "mouseover") { - window.setTimeout(load(node), 100); - } else { - load(node)() // all other events trigger immediately. - } - } - }) - - // Special handling for certain built-in event handlers - switch (on) { - - case "mouseover": - // Mirror `touchstart` events (fires immediately) - node.addEventListener("touchstart", load(node)); - - // WHhen the mouse leaves, immediately disable the preload - node.addEventListener("mouseout", function(evt) { - if ((evt.target === node) && (node.preloadState === "READY")) { - node.preloadState = "PAUSE"; - } - }) - break; - - case "mousedown": - // Mirror `touchstart` events (fires immediately) - node.addEventListener("touchstart", load(node)); - break; - } - - // Mark the node as ready to run. - node.preloadState = "PAUSE"; - node.preloadAlways = always; - htmx.trigger(node, "preload:init") // This event can be used to load content immediately. - } - - // Search for all child nodes that have a "preload" attribute - event.target.querySelectorAll("[preload]").forEach(function(node) { - - // Initialize the node with the "preload" attribute - init(node) - - // Initialize all child elements that are anchors or have `hx-get` (use with care) - node.querySelectorAll("a,[hx-get],[data-hx-get]").forEach(init) - }) - } -}) diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/remove-me.js b/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/remove-me.js deleted file mode 100644 index 42be99327d9..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/remove-me.js +++ /dev/null @@ -1,27 +0,0 @@ -(function(){ - function maybeRemoveMe(elt) { - var timing = elt.getAttribute("remove-me") || elt.getAttribute("data-remove-me"); - if (timing) { - setTimeout(function () { - elt.parentElement.removeChild(elt); - }, htmx.parseInterval(timing)); - } - } - - htmx.defineExtension('remove-me', { - onEvent: function (name, evt) { - if (name === "htmx:afterProcessNode") { - var elt = evt.detail.elt; - if (elt.getAttribute) { - maybeRemoveMe(elt); - if (elt.querySelectorAll) { - var children = elt.querySelectorAll("[remove-me], [data-remove-me]"); - for (var i = 0; i < children.length; i++) { - maybeRemoveMe(children[i]); - } - } - } - } - } - }); -})(); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/response-targets.js b/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/response-targets.js deleted file mode 100644 index dd6fd41820f..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/response-targets.js +++ /dev/null @@ -1,130 +0,0 @@ -(function(){ - - /** @type {import("../htmx").HtmxInternalApi} */ - var api; - - var attrPrefix = 'hx-target-'; - - // IE11 doesn't support string.startsWith - function startsWith(str, prefix) { - return str.substring(0, prefix.length) === prefix - } - - /** - * @param {HTMLElement} elt - * @param {number} respCode - * @returns {HTMLElement | null} - */ - function getRespCodeTarget(elt, respCodeNumber) { - if (!elt || !respCodeNumber) return null; - - var respCode = respCodeNumber.toString(); - - // '*' is the original syntax, as the obvious character for a wildcard. - // The 'x' alternative was added for maximum compatibility with HTML - // templating engines, due to ambiguity around which characters are - // supported in HTML attributes. - // - // Start with the most specific possible attribute and generalize from - // there. - var attrPossibilities = [ - respCode, - - respCode.substr(0, 2) + '*', - respCode.substr(0, 2) + 'x', - - respCode.substr(0, 1) + '*', - respCode.substr(0, 1) + 'x', - respCode.substr(0, 1) + '**', - respCode.substr(0, 1) + 'xx', - - '*', - 'x', - '***', - 'xxx', - ]; - if (startsWith(respCode, '4') || startsWith(respCode, '5')) { - attrPossibilities.push('error'); - } - - for (var i = 0; i < attrPossibilities.length; i++) { - var attr = attrPrefix + attrPossibilities[i]; - var attrValue = api.getClosestAttributeValue(elt, attr); - if (attrValue) { - if (attrValue === "this") { - return api.findThisElement(elt, attr); - } else { - return api.querySelectorExt(elt, attrValue); - } - } - } - - return null; - } - - /** @param {Event} evt */ - function handleErrorFlag(evt) { - if (evt.detail.isError) { - if (htmx.config.responseTargetUnsetsError) { - evt.detail.isError = false; - } - } else if (htmx.config.responseTargetSetsError) { - evt.detail.isError = true; - } - } - - htmx.defineExtension('response-targets', { - - /** @param {import("../htmx").HtmxInternalApi} apiRef */ - init: function (apiRef) { - api = apiRef; - - if (htmx.config.responseTargetUnsetsError === undefined) { - htmx.config.responseTargetUnsetsError = true; - } - if (htmx.config.responseTargetSetsError === undefined) { - htmx.config.responseTargetSetsError = false; - } - if (htmx.config.responseTargetPrefersExisting === undefined) { - htmx.config.responseTargetPrefersExisting = false; - } - if (htmx.config.responseTargetPrefersRetargetHeader === undefined) { - htmx.config.responseTargetPrefersRetargetHeader = true; - } - }, - - /** - * @param {string} name - * @param {Event} evt - */ - onEvent: function (name, evt) { - if (name === "htmx:beforeSwap" && - evt.detail.xhr && - evt.detail.xhr.status !== 200) { - if (evt.detail.target) { - if (htmx.config.responseTargetPrefersExisting) { - evt.detail.shouldSwap = true; - handleErrorFlag(evt); - return true; - } - if (htmx.config.responseTargetPrefersRetargetHeader && - evt.detail.xhr.getAllResponseHeaders().match(/HX-Retarget:/i)) { - evt.detail.shouldSwap = true; - handleErrorFlag(evt); - return true; - } - } - if (!evt.detail.requestConfig) { - return true; - } - var target = getRespCodeTarget(evt.detail.requestConfig.elt, evt.detail.xhr.status); - if (target) { - handleErrorFlag(evt); - evt.detail.shouldSwap = true; - evt.detail.target = target; - } - return true; - } - } - }); -})(); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/restored.js b/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/restored.js deleted file mode 100644 index 6f65267ce0a..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/restored.js +++ /dev/null @@ -1,15 +0,0 @@ -htmx.defineExtension('restored', { - onEvent : function(name, evt) { - if (name === 'htmx:restored'){ - var restoredElts = evt.detail.document.querySelectorAll( - "[hx-trigger='restored'],[data-hx-trigger='restored']" - ); - // need a better way to do this, would prefer to just trigger from evt.detail.elt - var foundElt = Array.from(restoredElts).find( - (x) => (x.outerHTML === evt.detail.elt.outerHTML) - ); - var restoredEvent = evt.detail.triggerEvent(foundElt, 'restored'); - } - return; - } -}) \ No newline at end of file diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/sse.js b/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/sse.js deleted file mode 100644 index 28c4dd32a15..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/sse.js +++ /dev/null @@ -1,369 +0,0 @@ -/* -Server Sent Events Extension -============================ -This extension adds support for Server Sent Events to htmx. See /www/extensions/sse.md for usage instructions. - -*/ - -(function() { - - /** @type {import("../htmx").HtmxInternalApi} */ - var api; - - htmx.defineExtension("sse", { - - /** - * Init saves the provided reference to the internal HTMX API. - * - * @param {import("../htmx").HtmxInternalApi} api - * @returns void - */ - init: function(apiRef) { - // store a reference to the internal API. - api = apiRef; - - // set a function in the public API for creating new EventSource objects - if (htmx.createEventSource == undefined) { - htmx.createEventSource = createEventSource; - } - }, - - /** - * onEvent handles all events passed to this extension. - * - * @param {string} name - * @param {Event} evt - * @returns void - */ - onEvent: function(name, evt) { - - var parent = evt.target || evt.detail.elt; - switch (name) { - - case "htmx:beforeCleanupElement": - var internalData = api.getInternalData(parent) - // Try to remove remove an EventSource when elements are removed - if (internalData.sseEventSource) { - internalData.sseEventSource.close(); - } - - return; - - // Try to create EventSources when elements are processed - case "htmx:afterProcessNode": - ensureEventSourceOnElement(parent); - } - } - }); - - /////////////////////////////////////////////// - // HELPER FUNCTIONS - /////////////////////////////////////////////// - - - /** - * createEventSource is the default method for creating new EventSource objects. - * it is hoisted into htmx.config.createEventSource to be overridden by the user, if needed. - * - * @param {string} url - * @returns EventSource - */ - function createEventSource(url) { - return new EventSource(url, { withCredentials: true }); - } - - function splitOnWhitespace(trigger) { - return trigger.trim().split(/\s+/); - } - - function getLegacySSEURL(elt) { - var legacySSEValue = api.getAttributeValue(elt, "hx-sse"); - if (legacySSEValue) { - var values = splitOnWhitespace(legacySSEValue); - for (var i = 0; i < values.length; i++) { - var value = values[i].split(/:(.+)/); - if (value[0] === "connect") { - return value[1]; - } - } - } - } - - function getLegacySSESwaps(elt) { - var legacySSEValue = api.getAttributeValue(elt, "hx-sse"); - var returnArr = []; - if (legacySSEValue != null) { - var values = splitOnWhitespace(legacySSEValue); - for (var i = 0; i < values.length; i++) { - var value = values[i].split(/:(.+)/); - if (value[0] === "swap") { - returnArr.push(value[1]); - } - } - } - return returnArr; - } - - /** - * registerSSE looks for attributes that can contain sse events, right - * now hx-trigger and sse-swap and adds listeners based on these attributes too - * the closest event source - * - * @param {HTMLElement} elt - */ - function registerSSE(elt) { - // Add message handlers for every `sse-swap` attribute - queryAttributeOnThisOrChildren(elt, "sse-swap").forEach(function (child) { - // Find closest existing event source - var sourceElement = api.getClosestMatch(child, hasEventSource); - if (sourceElement == null) { - // api.triggerErrorEvent(elt, "htmx:noSSESourceError") - return null; // no eventsource in parentage, orphaned element - } - - // Set internalData and source - var internalData = api.getInternalData(sourceElement); - var source = internalData.sseEventSource; - - var sseSwapAttr = api.getAttributeValue(child, "sse-swap"); - if (sseSwapAttr) { - var sseEventNames = sseSwapAttr.split(","); - } else { - var sseEventNames = getLegacySSESwaps(child); - } - - for (var i = 0; i < sseEventNames.length; i++) { - var sseEventName = sseEventNames[i].trim(); - var listener = function(event) { - - // If the source is missing then close SSE - if (maybeCloseSSESource(sourceElement)) { - return; - } - - // If the body no longer contains the element, remove the listener - if (!api.bodyContains(child)) { - source.removeEventListener(sseEventName, listener); - return; - } - - // swap the response into the DOM and trigger a notification - if(!api.triggerEvent(elt, "htmx:sseBeforeMessage", event)) { - return; - } - swap(child, event.data); - api.triggerEvent(elt, "htmx:sseMessage", event); - }; - - // Register the new listener - api.getInternalData(child).sseEventListener = listener; - source.addEventListener(sseEventName, listener); - } - }); - - // Add message handlers for every `hx-trigger="sse:*"` attribute - queryAttributeOnThisOrChildren(elt, "hx-trigger").forEach(function(child) { - // Find closest existing event source - var sourceElement = api.getClosestMatch(child, hasEventSource); - if (sourceElement == null) { - // api.triggerErrorEvent(elt, "htmx:noSSESourceError") - return null; // no eventsource in parentage, orphaned element - } - - // Set internalData and source - var internalData = api.getInternalData(sourceElement); - var source = internalData.sseEventSource; - - var sseEventName = api.getAttributeValue(child, "hx-trigger"); - if (sseEventName == null) { - return; - } - - // Only process hx-triggers for events with the "sse:" prefix - if (sseEventName.slice(0, 4) != "sse:") { - return; - } - - // remove the sse: prefix from here on out - sseEventName = sseEventName.substr(4); - - var listener = function() { - if (maybeCloseSSESource(sourceElement)) { - return - } - - if (!api.bodyContains(child)) { - source.removeEventListener(sseEventName, listener); - } - } - }); - } - - /** - * ensureEventSourceOnElement creates a new EventSource connection on the provided element. - * If a usable EventSource already exists, then it is returned. If not, then a new EventSource - * is created and stored in the element's internalData. - * @param {HTMLElement} elt - * @param {number} retryCount - * @returns {EventSource | null} - */ - function ensureEventSourceOnElement(elt, retryCount) { - - if (elt == null) { - return null; - } - - // handle extension source creation attribute - queryAttributeOnThisOrChildren(elt, "sse-connect").forEach(function(child) { - var sseURL = api.getAttributeValue(child, "sse-connect"); - if (sseURL == null) { - return; - } - - ensureEventSource(child, sseURL, retryCount); - }); - - // handle legacy sse, remove for HTMX2 - queryAttributeOnThisOrChildren(elt, "hx-sse").forEach(function(child) { - var sseURL = getLegacySSEURL(child); - if (sseURL == null) { - return; - } - - ensureEventSource(child, sseURL, retryCount); - }); - - registerSSE(elt); - } - - function ensureEventSource(elt, url, retryCount) { - var source = htmx.createEventSource(url); - - source.onerror = function(err) { - - // Log an error event - api.triggerErrorEvent(elt, "htmx:sseError", { error: err, source: source }); - - // If parent no longer exists in the document, then clean up this EventSource - if (maybeCloseSSESource(elt)) { - return; - } - - // Otherwise, try to reconnect the EventSource - if (source.readyState === EventSource.CLOSED) { - retryCount = retryCount || 0; - var timeout = Math.random() * (2 ^ retryCount) * 500; - window.setTimeout(function() { - ensureEventSourceOnElement(elt, Math.min(7, retryCount + 1)); - }, timeout); - } - }; - - source.onopen = function(evt) { - api.triggerEvent(elt, "htmx:sseOpen", { source: source }); - } - - api.getInternalData(elt).sseEventSource = source; - } - - /** - * maybeCloseSSESource confirms that the parent element still exists. - * If not, then any associated SSE source is closed and the function returns true. - * - * @param {HTMLElement} elt - * @returns boolean - */ - function maybeCloseSSESource(elt) { - if (!api.bodyContains(elt)) { - var source = api.getInternalData(elt).sseEventSource; - if (source != undefined) { - source.close(); - // source = null - return true; - } - } - return false; - } - - /** - * queryAttributeOnThisOrChildren returns all nodes that contain the requested attributeName, INCLUDING THE PROVIDED ROOT ELEMENT. - * - * @param {HTMLElement} elt - * @param {string} attributeName - */ - function queryAttributeOnThisOrChildren(elt, attributeName) { - - var result = []; - - // If the parent element also contains the requested attribute, then add it to the results too. - if (api.hasAttribute(elt, attributeName)) { - result.push(elt); - } - - // Search all child nodes that match the requested attribute - elt.querySelectorAll("[" + attributeName + "], [data-" + attributeName + "]").forEach(function(node) { - result.push(node); - }); - - return result; - } - - /** - * @param {HTMLElement} elt - * @param {string} content - */ - function swap(elt, content) { - - api.withExtensions(elt, function(extension) { - content = extension.transformResponse(content, null, elt); - }); - - var swapSpec = api.getSwapSpecification(elt); - var target = api.getTarget(elt); - var settleInfo = api.makeSettleInfo(elt); - - api.selectAndSwap(swapSpec.swapStyle, target, elt, content, settleInfo); - - settleInfo.elts.forEach(function(elt) { - if (elt.classList) { - elt.classList.add(htmx.config.settlingClass); - } - api.triggerEvent(elt, 'htmx:beforeSettle'); - }); - - // Handle settle tasks (with delay if requested) - if (swapSpec.settleDelay > 0) { - setTimeout(doSettle(settleInfo), swapSpec.settleDelay); - } else { - doSettle(settleInfo)(); - } - } - - /** - * doSettle mirrors much of the functionality in htmx that - * settles elements after their content has been swapped. - * TODO: this should be published by htmx, and not duplicated here - * @param {import("../htmx").HtmxSettleInfo} settleInfo - * @returns () => void - */ - function doSettle(settleInfo) { - - return function() { - settleInfo.tasks.forEach(function(task) { - task.call(); - }); - - settleInfo.elts.forEach(function(elt) { - if (elt.classList) { - elt.classList.remove(htmx.config.settlingClass); - } - api.triggerEvent(elt, 'htmx:afterSettle'); - }); - } - } - - function hasEventSource(node) { - return api.getInternalData(node).sseEventSource != null; - } - -})(); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/ws.js b/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/ws.js deleted file mode 100644 index c1e29620b6a..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/src/ext/ws.js +++ /dev/null @@ -1,476 +0,0 @@ -/* -WebSockets Extension -============================ -This extension adds support for WebSockets to htmx. See /www/extensions/ws.md for usage instructions. -*/ - -(function () { - - /** @type {import("../htmx").HtmxInternalApi} */ - var api; - - htmx.defineExtension("ws", { - - /** - * init is called once, when this extension is first registered. - * @param {import("../htmx").HtmxInternalApi} apiRef - */ - init: function (apiRef) { - - // Store reference to internal API - api = apiRef; - - // Default function for creating new EventSource objects - if (!htmx.createWebSocket) { - htmx.createWebSocket = createWebSocket; - } - - // Default setting for reconnect delay - if (!htmx.config.wsReconnectDelay) { - htmx.config.wsReconnectDelay = "full-jitter"; - } - }, - - /** - * onEvent handles all events passed to this extension. - * - * @param {string} name - * @param {Event} evt - */ - onEvent: function (name, evt) { - var parent = evt.target || evt.detail.elt; - - switch (name) { - - // Try to close the socket when elements are removed - case "htmx:beforeCleanupElement": - - var internalData = api.getInternalData(parent) - - if (internalData.webSocket) { - internalData.webSocket.close(); - } - return; - - // Try to create websockets when elements are processed - case "htmx:beforeProcessNode": - forEach(queryAttributeOnThisOrChildren(parent, "ws-connect"), function (child) { - ensureWebSocket(child) - }); - forEach(queryAttributeOnThisOrChildren(parent, "ws-send"), function (child) { - ensureWebSocketSend(child) - }); - } - } - }); - - function splitOnWhitespace(trigger) { - return trigger.trim().split(/\s+/); - } - - function getLegacyWebsocketURL(elt) { - var legacySSEValue = api.getAttributeValue(elt, "hx-ws"); - if (legacySSEValue) { - var values = splitOnWhitespace(legacySSEValue); - for (var i = 0; i < values.length; i++) { - var value = values[i].split(/:(.+)/); - if (value[0] === "connect") { - return value[1]; - } - } - } - } - - /** - * ensureWebSocket creates a new WebSocket on the designated element, using - * the element's "ws-connect" attribute. - * @param {HTMLElement} socketElt - * @returns - */ - function ensureWebSocket(socketElt) { - - // If the element containing the WebSocket connection no longer exists, then - // do not connect/reconnect the WebSocket. - if (!api.bodyContains(socketElt)) { - return; - } - - // Get the source straight from the element's value - var wssSource = api.getAttributeValue(socketElt, "ws-connect") - - if (wssSource == null || wssSource === "") { - var legacySource = getLegacyWebsocketURL(socketElt); - if (legacySource == null) { - return; - } else { - wssSource = legacySource; - } - } - - // Guarantee that the wssSource value is a fully qualified URL - if (wssSource.indexOf("/") === 0) { - var base_part = location.hostname + (location.port ? ':' + location.port : ''); - if (location.protocol === 'https:') { - wssSource = "wss://" + base_part + wssSource; - } else if (location.protocol === 'http:') { - wssSource = "ws://" + base_part + wssSource; - } - } - - var socketWrapper = createWebsocketWrapper(socketElt, function () { - return htmx.createWebSocket(wssSource) - }); - - socketWrapper.addEventListener('message', function (event) { - if (maybeCloseWebSocketSource(socketElt)) { - return; - } - - var response = event.data; - if (!api.triggerEvent(socketElt, "htmx:wsBeforeMessage", { - message: response, - socketWrapper: socketWrapper.publicInterface - })) { - return; - } - - api.withExtensions(socketElt, function (extension) { - response = extension.transformResponse(response, null, socketElt); - }); - - var settleInfo = api.makeSettleInfo(socketElt); - var fragment = api.makeFragment(response); - - if (fragment.children.length) { - var children = Array.from(fragment.children); - for (var i = 0; i < children.length; i++) { - api.oobSwap(api.getAttributeValue(children[i], "hx-swap-oob") || "true", children[i], settleInfo); - } - } - - api.settleImmediately(settleInfo.tasks); - api.triggerEvent(socketElt, "htmx:wsAfterMessage", { message: response, socketWrapper: socketWrapper.publicInterface }) - }); - - // Put the WebSocket into the HTML Element's custom data. - api.getInternalData(socketElt).webSocket = socketWrapper; - } - - /** - * @typedef {Object} WebSocketWrapper - * @property {WebSocket} socket - * @property {Array<{message: string, sendElt: Element}>} messageQueue - * @property {number} retryCount - * @property {(message: string, sendElt: Element) => void} sendImmediately sendImmediately sends message regardless of websocket connection state - * @property {(message: string, sendElt: Element) => void} send - * @property {(event: string, handler: Function) => void} addEventListener - * @property {() => void} handleQueuedMessages - * @property {() => void} init - * @property {() => void} close - */ - /** - * - * @param socketElt - * @param socketFunc - * @returns {WebSocketWrapper} - */ - function createWebsocketWrapper(socketElt, socketFunc) { - var wrapper = { - socket: null, - messageQueue: [], - retryCount: 0, - - /** @type {Object} */ - events: {}, - - addEventListener: function (event, handler) { - if (this.socket) { - this.socket.addEventListener(event, handler); - } - - if (!this.events[event]) { - this.events[event] = []; - } - - this.events[event].push(handler); - }, - - sendImmediately: function (message, sendElt) { - if (!this.socket) { - api.triggerErrorEvent() - } - if (!sendElt || api.triggerEvent(sendElt, 'htmx:wsBeforeSend', { - message: message, - socketWrapper: this.publicInterface - })) { - this.socket.send(message); - sendElt && api.triggerEvent(sendElt, 'htmx:wsAfterSend', { - message: message, - socketWrapper: this.publicInterface - }) - } - }, - - send: function (message, sendElt) { - if (this.socket.readyState !== this.socket.OPEN) { - this.messageQueue.push({ message: message, sendElt: sendElt }); - } else { - this.sendImmediately(message, sendElt); - } - }, - - handleQueuedMessages: function () { - while (this.messageQueue.length > 0) { - var queuedItem = this.messageQueue[0] - if (this.socket.readyState === this.socket.OPEN) { - this.sendImmediately(queuedItem.message, queuedItem.sendElt); - this.messageQueue.shift(); - } else { - break; - } - } - }, - - init: function () { - if (this.socket && this.socket.readyState === this.socket.OPEN) { - // Close discarded socket - this.socket.close() - } - - // Create a new WebSocket and event handlers - /** @type {WebSocket} */ - var socket = socketFunc(); - - // The event.type detail is added for interface conformance with the - // other two lifecycle events (open and close) so a single handler method - // can handle them polymorphically, if required. - api.triggerEvent(socketElt, "htmx:wsConnecting", { event: { type: 'connecting' } }); - - this.socket = socket; - - socket.onopen = function (e) { - wrapper.retryCount = 0; - api.triggerEvent(socketElt, "htmx:wsOpen", { event: e, socketWrapper: wrapper.publicInterface }); - wrapper.handleQueuedMessages(); - } - - socket.onclose = function (e) { - // If socket should not be connected, stop further attempts to establish connection - // If Abnormal Closure/Service Restart/Try Again Later, then set a timer to reconnect after a pause. - if (!maybeCloseWebSocketSource(socketElt) && [1006, 1012, 1013].indexOf(e.code) >= 0) { - var delay = getWebSocketReconnectDelay(wrapper.retryCount); - setTimeout(function () { - wrapper.retryCount += 1; - wrapper.init(); - }, delay); - } - - // Notify client code that connection has been closed. Client code can inspect `event` field - // to determine whether closure has been valid or abnormal - api.triggerEvent(socketElt, "htmx:wsClose", { event: e, socketWrapper: wrapper.publicInterface }) - }; - - socket.onerror = function (e) { - api.triggerErrorEvent(socketElt, "htmx:wsError", { error: e, socketWrapper: wrapper }); - maybeCloseWebSocketSource(socketElt); - }; - - var events = this.events; - Object.keys(events).forEach(function (k) { - events[k].forEach(function (e) { - socket.addEventListener(k, e); - }) - }); - }, - - close: function () { - this.socket.close() - } - } - - wrapper.init(); - - wrapper.publicInterface = { - send: wrapper.send.bind(wrapper), - sendImmediately: wrapper.sendImmediately.bind(wrapper), - queue: wrapper.messageQueue - }; - - return wrapper; - } - - /** - * ensureWebSocketSend attaches trigger handles to elements with - * "ws-send" attribute - * @param {HTMLElement} elt - */ - function ensureWebSocketSend(elt) { - var legacyAttribute = api.getAttributeValue(elt, "hx-ws"); - if (legacyAttribute && legacyAttribute !== 'send') { - return; - } - - var webSocketParent = api.getClosestMatch(elt, hasWebSocket) - processWebSocketSend(webSocketParent, elt); - } - - /** - * hasWebSocket function checks if a node has webSocket instance attached - * @param {HTMLElement} node - * @returns {boolean} - */ - function hasWebSocket(node) { - return api.getInternalData(node).webSocket != null; - } - - /** - * processWebSocketSend adds event listeners to the
    element so that - * messages can be sent to the WebSocket server when the form is submitted. - * @param {HTMLElement} socketElt - * @param {HTMLElement} sendElt - */ - function processWebSocketSend(socketElt, sendElt) { - var nodeData = api.getInternalData(sendElt); - var triggerSpecs = api.getTriggerSpecs(sendElt); - triggerSpecs.forEach(function (ts) { - api.addTriggerHandler(sendElt, ts, nodeData, function (elt, evt) { - if (maybeCloseWebSocketSource(socketElt)) { - return; - } - - /** @type {WebSocketWrapper} */ - var socketWrapper = api.getInternalData(socketElt).webSocket; - var headers = api.getHeaders(sendElt, api.getTarget(sendElt)); - var results = api.getInputValues(sendElt, 'post'); - var errors = results.errors; - var rawParameters = results.values; - var expressionVars = api.getExpressionVars(sendElt); - var allParameters = api.mergeObjects(rawParameters, expressionVars); - var filteredParameters = api.filterValues(allParameters, sendElt); - - var sendConfig = { - parameters: filteredParameters, - unfilteredParameters: allParameters, - headers: headers, - errors: errors, - - triggeringEvent: evt, - messageBody: undefined, - socketWrapper: socketWrapper.publicInterface - }; - - if (!api.triggerEvent(elt, 'htmx:wsConfigSend', sendConfig)) { - return; - } - - if (errors && errors.length > 0) { - api.triggerEvent(elt, 'htmx:validation:halted', errors); - return; - } - - var body = sendConfig.messageBody; - if (body === undefined) { - var toSend = Object.assign({}, sendConfig.parameters); - if (sendConfig.headers) - toSend['HEADERS'] = headers; - body = JSON.stringify(toSend); - } - - socketWrapper.send(body, elt); - - if (evt && api.shouldCancel(evt, elt)) { - evt.preventDefault(); - } - }); - }); - } - - /** - * getWebSocketReconnectDelay is the default easing function for WebSocket reconnects. - * @param {number} retryCount // The number of retries that have already taken place - * @returns {number} - */ - function getWebSocketReconnectDelay(retryCount) { - - /** @type {"full-jitter" | ((retryCount:number) => number)} */ - var delay = htmx.config.wsReconnectDelay; - if (typeof delay === 'function') { - return delay(retryCount); - } - if (delay === 'full-jitter') { - var exp = Math.min(retryCount, 6); - var maxDelay = 1000 * Math.pow(2, exp); - return maxDelay * Math.random(); - } - - logError('htmx.config.wsReconnectDelay must either be a function or the string "full-jitter"'); - } - - /** - * maybeCloseWebSocketSource checks to the if the element that created the WebSocket - * still exists in the DOM. If NOT, then the WebSocket is closed and this function - * returns TRUE. If the element DOES EXIST, then no action is taken, and this function - * returns FALSE. - * - * @param {*} elt - * @returns - */ - function maybeCloseWebSocketSource(elt) { - if (!api.bodyContains(elt)) { - api.getInternalData(elt).webSocket.close(); - return true; - } - return false; - } - - /** - * createWebSocket is the default method for creating new WebSocket objects. - * it is hoisted into htmx.createWebSocket to be overridden by the user, if needed. - * - * @param {string} url - * @returns WebSocket - */ - function createWebSocket(url) { - var sock = new WebSocket(url, []); - sock.binaryType = htmx.config.wsBinaryType; - return sock; - } - - /** - * queryAttributeOnThisOrChildren returns all nodes that contain the requested attributeName, INCLUDING THE PROVIDED ROOT ELEMENT. - * - * @param {HTMLElement} elt - * @param {string} attributeName - */ - function queryAttributeOnThisOrChildren(elt, attributeName) { - - var result = [] - - // If the parent element also contains the requested attribute, then add it to the results too. - if (api.hasAttribute(elt, attributeName) || api.hasAttribute(elt, "hx-ws")) { - result.push(elt); - } - - // Search all child nodes that match the requested attribute - elt.querySelectorAll("[" + attributeName + "], [data-" + attributeName + "], [data-hx-ws], [hx-ws]").forEach(function (node) { - result.push(node) - }) - - return result - } - - /** - * @template T - * @param {T[]} arr - * @param {(T) => void} func - */ - function forEach(arr, func) { - if (arr) { - for (var i = 0; i < arr.length; i++) { - func(arr[i]); - } - } - } - -})(); - diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/src/htmx.d.ts b/src/test/resources/libraries/htmx/htmx-1.9.11/src/htmx.d.ts deleted file mode 100644 index a545692e5de..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/src/htmx.d.ts +++ /dev/null @@ -1,487 +0,0 @@ -// https://htmx.org/reference/#api - -/** - * This method adds a class to the given element. - * - * https://htmx.org/api/#addClass - * - * @param elt the element to add the class to - * @param clazz the class to add - * @param delay the delay (in milliseconds before class is added) - */ -export function addClass(elt: Element, clazz: string, delay?: number): void; - -/** - * Issues an htmx-style AJAX request - * - * https://htmx.org/api/#ajax - * - * @param verb 'GET', 'POST', etc. - * @param path the URL path to make the AJAX - * @param element the element to target (defaults to the **body**) - * @returns Promise that resolves immediately if no request is sent, or when the request is complete - */ -export function ajax(verb: string, path: string, element?: Element): Promise; - -/** - * Issues an htmx-style AJAX request - * - * https://htmx.org/api/#ajax - * - * @param verb 'GET', 'POST', etc. - * @param path the URL path to make the AJAX - * @param selector a selector for the target - * @returns Promise that resolves immediately if no request is sent, or when the request is complete - */ -export function ajax(verb: string, path: string, selector: string): Promise; - -/** - * Issues an htmx-style AJAX request - * - * https://htmx.org/api/#ajax - * - * @param verb 'GET', 'POST', etc. - * @param path the URL path to make the AJAX - * @param context a context object that contains any of the following - * @returns Promise that resolves immediately if no request is sent, or when the request is complete - */ -export function ajax( - verb: string, - path: string, - context: Partial<{ source: any; event: any; handler: any; target: any; swap: any; values: any; headers: any; select: any }> -): Promise; - -/** - * Finds the closest matching element in the given elements parentage, inclusive of the element - * - * https://htmx.org/api/#closest - * - * @param elt the element to find the selector from - * @param selector the selector to find - */ -export function closest(elt: Element, selector: string): Element | null; - -/** - * A property holding the configuration htmx uses at runtime. - * - * Note that using a [meta tag](https://htmx.org/docs/#config) is the preferred mechanism for setting these properties. - * - * https://htmx.org/api/#config - */ -export var config: HtmxConfig; - -/** - * A property used to create new [Server Sent Event](https://htmx.org/docs/#sse) sources. This can be updated to provide custom SSE setup. - * - * https://htmx.org/api/#createEventSource - */ -export var createEventSource: (url: string) => EventSource; - -/** - * A property used to create new [WebSocket](https://htmx.org/docs/#websockets). This can be updated to provide custom WebSocket setup. - * - * https://htmx.org/api/#createWebSocket - */ -export var createWebSocket: (url: string) => WebSocket; - -/** - * Defines a new htmx [extension](https://htmx.org/extensions). - * - * https://htmx.org/api/#defineExtension - * - * @param name the extension name - * @param ext the extension definition - */ -export function defineExtension(name: string, ext: HtmxExtension): void; - -/** - * Finds an element matching the selector - * - * https://htmx.org/api/#find - * - * @param selector the selector to match - */ -export function find(selector: string): Element | null; - -/** - * Finds an element matching the selector - * - * https://htmx.org/api/#find - * - * @param elt the root element to find the matching element in, inclusive - * @param selector the selector to match - */ -export function find(elt: Element, selector: string): Element | null; - -/** - * Finds all elements matching the selector - * - * https://htmx.org/api/#findAll - * - * @param selector the selector to match - */ -export function findAll(selector: string): NodeListOf; - -/** - * Finds all elements matching the selector - * - * https://htmx.org/api/#findAll - * - * @param elt the root element to find the matching elements in, inclusive - * @param selector the selector to match - */ -export function findAll(elt: Element, selector: string): NodeListOf; - -/** - * Log all htmx events, useful for debugging. - * - * https://htmx.org/api/#logAll - */ -export function logAll(): void; - -/** - * The logger htmx uses to log with - * - * https://htmx.org/api/#logger - */ -export var logger: (elt: Element, eventName: string, detail: any) => void | null; - -/** - * Removes an event listener from an element - * - * https://htmx.org/api/#off - * - * @param eventName the event name to remove the listener from - * @param listener the listener to remove - */ -export function off(eventName: string, listener: (evt: Event) => void): (evt: Event) => void; - -/** - * Removes an event listener from an element - * - * https://htmx.org/api/#off - * - * @param target the element to remove the listener from - * @param eventName the event name to remove the listener from - * @param listener the listener to remove - */ -export function off(target: string, eventName: string, listener: (evt: Event) => void): (evt: Event) => void; - -/** - * Adds an event listener to an element - * - * https://htmx.org/api/#on - * - * @param eventName the event name to add the listener for - * @param listener the listener to add - */ -export function on(eventName: string, listener: (evt: Event) => void): (evt: Event) => void; - -/** - * Adds an event listener to an element - * - * https://htmx.org/api/#on - * - * @param target the element to add the listener to - * @param eventName the event name to add the listener for - * @param listener the listener to add - */ -export function on(target: string, eventName: string, listener: (evt: Event) => void): (evt: Event) => void; - -/** - * Adds a callback for the **htmx:load** event. This can be used to process new content, for example initializing the content with a javascript library - * - * https://htmx.org/api/#onLoad - * - * @param callback the callback to call on newly loaded content - */ -export function onLoad(callback: (element: Element) => void): void; - -/** - * Parses an interval string consistent with the way htmx does. Useful for plugins that have timing-related attributes. - * - * Caution: Accepts an int followed by either **s** or **ms**. All other values use **parseFloat** - * - * https://htmx.org/api/#parseInterval - * - * @param str timing string - */ -export function parseInterval(str: string): number; - -/** - * Processes new content, enabling htmx behavior. This can be useful if you have content that is added to the DOM outside of the normal htmx request cycle but still want htmx attributes to work. - * - * https://htmx.org/api/#process - * - * @param element element to process - */ -export function process(element: Element): void; - -/** - * Removes an element from the DOM - * - * https://htmx.org/api/#remove - * - * @param elt element to remove - * @param delay the delay (in milliseconds before element is removed) - */ -export function remove(elt: Element, delay?: number): void; - -/** - * Removes a class from the given element - * - * https://htmx.org/api/#removeClass - * - * @param elt element to remove the class from - * @param clazz the class to remove - * @param delay the delay (in milliseconds before class is removed) - */ -export function removeClass(elt: Element, clazz: string, delay?: number): void; - -/** - * Removes the given extension from htmx - * - * https://htmx.org/api/#removeExtension - * - * @param name the name of the extension to remove - */ -export function removeExtension(name: string): void; - -/** - * Takes the given class from its siblings, so that among its siblings, only the given element will have the class. - * - * https://htmx.org/api/#takeClass - * - * @param elt the element that will take the class - * @param clazz the class to take - */ -export function takeClass(elt: Element, clazz: string): void; - -/** - * Toggles the given class on an element - * - * https://htmx.org/api/#toggleClass - * - * @param elt the element to toggle the class on - * @param clazz the class to toggle - */ -export function toggleClass(elt: Element, clazz: string): void; - -/** - * Triggers a given event on an element - * - * https://htmx.org/api/#trigger - * - * @param elt the element to trigger the event on - * @param name the name of the event to trigger - * @param detail details for the event - */ -export function trigger(elt: Element, name: string, detail: any): void; - -/** - * Returns the input values that would resolve for a given element via the htmx value resolution mechanism - * - * https://htmx.org/api/#values - * - * @param elt the element to resolve values on - * @param requestType the request type (e.g. **get** or **post**) non-GET's will include the enclosing form of the element. Defaults to **post** - */ -export function values(elt: Element, requestType?: string): any; - -export const version: string; - -export interface HtmxConfig { - /** - * The attributes to settle during the settling phase. - * @default ["class", "style", "width", "height"] - */ - attributesToSettle?: ["class", "style", "width", "height"] | string[]; - /** - * If the focused element should be scrolled into view. - * @default false - */ - defaultFocusScroll?: boolean; - /** - * The default delay between completing the content swap and settling attributes. - * @default 20 - */ - defaultSettleDelay?: number; - /** - * The default delay between receiving a response from the server and doing the swap. - * @default 0 - */ - defaultSwapDelay?: number; - /** - * The default swap style to use if **[hx-swap](https://htmx.org/attributes/hx-swap)** is omitted. - * @default "innerHTML" - */ - defaultSwapStyle?: "innerHTML" | string; - /** - * The number of pages to keep in **localStorage** for history support. - * @default 10 - */ - historyCacheSize?: number; - /** - * Whether or not to use history. - * @default true - */ - historyEnabled?: boolean; - /** - * If true, htmx will inject a small amount of CSS into the page to make indicators invisible unless the **htmx-indicator** class is present. - * @default true - */ - includeIndicatorStyles?: boolean; - /** - * The class to place on indicators when a request is in flight. - * @default "htmx-indicator" - */ - indicatorClass?: "htmx-indicator" | string; - /** - * The class to place on triggering elements when a request is in flight. - * @default "htmx-request" - */ - requestClass?: "htmx-request" | string; - /** - * The class to temporarily place on elements that htmx has added to the DOM. - * @default "htmx-added" - */ - addedClass?: "htmx-added" | string; - /** - * The class to place on target elements when htmx is in the settling phase. - * @default "htmx-settling" - */ - settlingClass?: "htmx-settling" | string; - /** - * The class to place on target elements when htmx is in the swapping phase. - * @default "htmx-swapping" - */ - swappingClass?: "htmx-swapping" | string; - /** - * Allows the use of eval-like functionality in htmx, to enable **hx-vars**, trigger conditions & script tag evaluation. Can be set to **false** for CSP compatibility. - * @default true - */ - allowEval?: boolean; - /** - * Use HTML template tags for parsing content from the server. This allows you to use Out of Band content when returning things like table rows, but it is *not* IE11 compatible. - * @default false - */ - useTemplateFragments?: boolean; - /** - * Allow cross-site Access-Control requests using credentials such as cookies, authorization headers or TLS client certificates. - * @default false - */ - withCredentials?: boolean; - /** - * The default implementation of **getWebSocketReconnectDelay** for reconnecting after unexpected connection loss by the event code **Abnormal Closure**, **Service Restart** or **Try Again Later**. - * @default "full-jitter" - */ - wsReconnectDelay?: "full-jitter" | string | ((retryCount: number) => number); - // following don't appear in the docs - /** @default false */ - refreshOnHistoryMiss?: boolean; - /** @default 0 */ - timeout?: number; - /** @default "[hx-disable], [data-hx-disable]" */ - disableSelector?: "[hx-disable], [data-hx-disable]" | string; - /** @default "smooth" */ - scrollBehavior?: "smooth" | "auto"; - /** - * If set to false, disables the interpretation of script tags. - * @default true - */ - allowScriptTags?: boolean; - /** - * If set to true, disables htmx-based requests to non-origin hosts. - * @default false - */ - selfRequestsOnly?: boolean; - /** - * Whether or not the target of a boosted element is scrolled into the viewport. - * @default true - */ - scrollIntoViewOnBoost?: boolean; - /** - * If set, the nonce will be added to inline scripts. - * @default '' - */ - inlineScriptNonce?: string; - /** - * The type of binary data being received over the WebSocket connection - * @default 'blob' - */ - wsBinaryType?: 'blob' | 'arraybuffer'; - /** - * If set to true htmx will include a cache-busting parameter in GET requests to avoid caching partial responses by the browser - * @default false - */ - getCacheBusterParam?: boolean; - /** - * If set to true, htmx will use the View Transition API when swapping in new content. - * @default false - */ - globalViewTransitions?: boolean; - /** - * htmx will format requests with these methods by encoding their parameters in the URL, not the request body - * @default ["get"] - */ - methodsThatUseUrlParams?: ('get' | 'head' | 'post' | 'put' | 'delete' | 'connect' | 'options' | 'trace' | 'patch' )[]; - /** - * If set to true htmx will not update the title of the document when a title tag is found in new content - * @default false - */ - ignoreTitle?: boolean; -} - -export type HtmxEvent = "htmx:abort" - | "htmx:afterOnLoad" - | "htmx:afterProcessNode" - | "htmx:afterRequest" - | "htmx:afterSettle" - | "htmx:afterSwap" - | "htmx:beforeCleanupElement" - | "htmx:beforeOnLoad" - | "htmx:beforeProcessNode" - | "htmx:beforeRequest" - | "htmx:beforeSwap" - | "htmx:beforeSend" - | "htmx:configRequest" - | "htmx:confirm" - | "htmx:historyCacheError" - | "htmx:historyCacheMiss" - | "htmx:historyCacheMissError" - | "htmx:historyCacheMissLoad" - | "htmx:historyRestore" - | "htmx:load" - | "htmx:noSSESourceError" - | "htmx:onLoadError" - | "htmx:oobAfterSwap" - | "htmx:oobBeforeSwap" - | "htmx:oobErrorNoTarget" - | "htmx:prompt" - | "htmx:pushedIntoHistory" - | "htmx:responseError" - | "htmx:sendError" - | "htmx:sseError" - | "htmx:sseOpen" - | "htmx:swapError" - | "htmx:targetError" - | "htmx:timeout" - | "htmx:validation:validate" - | "htmx:validation:failed" - | "htmx:validation:halted" - | "htmx:xhr:abort" - | "htmx:xhr:loadend" - | "htmx:xhr:loadstart" - | "htmx:xhr:progress" -; - -/** - * https://htmx.org/extensions/#defining - */ -export interface HtmxExtension { - onEvent?: (name: HtmxEvent, evt: CustomEvent) => any; - transformResponse?: (text: any, xhr: XMLHttpRequest, elt: any) => any; - isInlineSwap?: (swapStyle: any) => any; - handleSwap?: (swapStyle: any, target: any, fragment: any, settleInfo: any) => any; - encodeParameters?: (xhr: XMLHttpRequest, parameters: any, elt: any) => any; -} diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/src/htmx.js b/src/test/resources/libraries/htmx/htmx-1.9.11/src/htmx.js deleted file mode 100644 index 0e31707b5ed..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/src/htmx.js +++ /dev/null @@ -1,3922 +0,0 @@ -// UMD insanity -// This code sets up support for (in order) AMD, ES6 modules, and globals. -(function (root, factory) { - //@ts-ignore - if (typeof define === 'function' && define.amd) { - // AMD. Register as an anonymous module. - //@ts-ignore - define([], factory); - } else if (typeof module === 'object' && module.exports) { - // Node. Does not work with strict CommonJS, but - // only CommonJS-like environments that support module.exports, - // like Node. - module.exports = factory(); - } else { - // Browser globals - root.htmx = root.htmx || factory(); - } -}(typeof self !== 'undefined' ? self : this, function () { -return (function () { - 'use strict'; - - // Public API - //** @type {import("./htmx").HtmxApi} */ - // TODO: list all methods in public API - var htmx = { - onLoad: onLoadHelper, - process: processNode, - on: addEventListenerImpl, - off: removeEventListenerImpl, - trigger : triggerEvent, - ajax : ajaxHelper, - find : find, - findAll : findAll, - closest : closest, - values : function(elt, type){ - var inputValues = getInputValues(elt, type || "post"); - return inputValues.values; - }, - remove : removeElement, - addClass : addClassToElement, - removeClass : removeClassFromElement, - toggleClass : toggleClassOnElement, - takeClass : takeClassForElement, - defineExtension : defineExtension, - removeExtension : removeExtension, - logAll : logAll, - logNone : logNone, - logger : null, - config : { - historyEnabled:true, - historyCacheSize:10, - refreshOnHistoryMiss:false, - defaultSwapStyle:'innerHTML', - defaultSwapDelay:0, - defaultSettleDelay:20, - includeIndicatorStyles:true, - indicatorClass:'htmx-indicator', - requestClass:'htmx-request', - addedClass:'htmx-added', - settlingClass:'htmx-settling', - swappingClass:'htmx-swapping', - allowEval:true, - allowScriptTags:true, - inlineScriptNonce:'', - attributesToSettle:["class", "style", "width", "height"], - withCredentials:false, - timeout:0, - wsReconnectDelay: 'full-jitter', - wsBinaryType: 'blob', - disableSelector: "[hx-disable], [data-hx-disable]", - useTemplateFragments: false, - scrollBehavior: 'smooth', - defaultFocusScroll: false, - getCacheBusterParam: false, - globalViewTransitions: false, - methodsThatUseUrlParams: ["get"], - selfRequestsOnly: false, - ignoreTitle: false, - scrollIntoViewOnBoost: true, - triggerSpecsCache: null, - }, - parseInterval:parseInterval, - _:internalEval, - createEventSource: function(url){ - return new EventSource(url, {withCredentials:true}) - }, - createWebSocket: function(url){ - var sock = new WebSocket(url, []); - sock.binaryType = htmx.config.wsBinaryType; - return sock; - }, - version: "1.9.11" - }; - - /** @type {import("./htmx").HtmxInternalApi} */ - var internalAPI = { - addTriggerHandler: addTriggerHandler, - bodyContains: bodyContains, - canAccessLocalStorage: canAccessLocalStorage, - findThisElement: findThisElement, - filterValues: filterValues, - hasAttribute: hasAttribute, - getAttributeValue: getAttributeValue, - getClosestAttributeValue: getClosestAttributeValue, - getClosestMatch: getClosestMatch, - getExpressionVars: getExpressionVars, - getHeaders: getHeaders, - getInputValues: getInputValues, - getInternalData: getInternalData, - getSwapSpecification: getSwapSpecification, - getTriggerSpecs: getTriggerSpecs, - getTarget: getTarget, - makeFragment: makeFragment, - mergeObjects: mergeObjects, - makeSettleInfo: makeSettleInfo, - oobSwap: oobSwap, - querySelectorExt: querySelectorExt, - selectAndSwap: selectAndSwap, - settleImmediately: settleImmediately, - shouldCancel: shouldCancel, - triggerEvent: triggerEvent, - triggerErrorEvent: triggerErrorEvent, - withExtensions: withExtensions, - } - - var VERBS = ['get', 'post', 'put', 'delete', 'patch']; - var VERB_SELECTOR = VERBS.map(function(verb){ - return "[hx-" + verb + "], [data-hx-" + verb + "]" - }).join(", "); - - var HEAD_TAG_REGEX = makeTagRegEx('head'), - TITLE_TAG_REGEX = makeTagRegEx('title'), - SVG_TAGS_REGEX = makeTagRegEx('svg', true); - - //==================================================================== - // Utilities - //==================================================================== - - /** - * @param {string} tag - * @param {boolean} global - * @returns {RegExp} - */ - function makeTagRegEx(tag, global = false) { - return new RegExp(`<${tag}(\\s[^>]*>|>)([\\s\\S]*?)<\\/${tag}>`, - global ? 'gim' : 'im'); - } - - function parseInterval(str) { - if (str == undefined) { - return undefined; - } - - let interval = NaN; - if (str.slice(-2) == "ms") { - interval = parseFloat(str.slice(0, -2)); - } else if (str.slice(-1) == "s") { - interval = parseFloat(str.slice(0, -1)) * 1000; - } else if (str.slice(-1) == "m") { - interval = parseFloat(str.slice(0, -1)) * 1000 * 60; - } else { - interval = parseFloat(str); - } - return isNaN(interval) ? undefined : interval; - } - - /** - * @param {HTMLElement} elt - * @param {string} name - * @returns {(string | null)} - */ - function getRawAttribute(elt, name) { - return elt.getAttribute && elt.getAttribute(name); - } - - // resolve with both hx and data-hx prefixes - function hasAttribute(elt, qualifiedName) { - return elt.hasAttribute && (elt.hasAttribute(qualifiedName) || - elt.hasAttribute("data-" + qualifiedName)); - } - - /** - * - * @param {HTMLElement} elt - * @param {string} qualifiedName - * @returns {(string | null)} - */ - function getAttributeValue(elt, qualifiedName) { - return getRawAttribute(elt, qualifiedName) || getRawAttribute(elt, "data-" + qualifiedName); - } - - /** - * @param {HTMLElement} elt - * @returns {HTMLElement | null} - */ - function parentElt(elt) { - return elt.parentElement; - } - - /** - * @returns {Document} - */ - function getDocument() { - return document; - } - - /** - * @param {HTMLElement} elt - * @param {(e:HTMLElement) => boolean} condition - * @returns {HTMLElement | null} - */ - function getClosestMatch(elt, condition) { - while (elt && !condition(elt)) { - elt = parentElt(elt); - } - - return elt ? elt : null; - } - - function getAttributeValueWithDisinheritance(initialElement, ancestor, attributeName){ - var attributeValue = getAttributeValue(ancestor, attributeName); - var disinherit = getAttributeValue(ancestor, "hx-disinherit"); - if (initialElement !== ancestor && disinherit && (disinherit === "*" || disinherit.split(" ").indexOf(attributeName) >= 0)) { - return "unset"; - } else { - return attributeValue - } - } - - /** - * @param {HTMLElement} elt - * @param {string} attributeName - * @returns {string | null} - */ - function getClosestAttributeValue(elt, attributeName) { - var closestAttr = null; - getClosestMatch(elt, function (e) { - return closestAttr = getAttributeValueWithDisinheritance(elt, e, attributeName); - }); - if (closestAttr !== "unset") { - return closestAttr; - } - } - - /** - * @param {HTMLElement} elt - * @param {string} selector - * @returns {boolean} - */ - function matches(elt, selector) { - // @ts-ignore: non-standard properties for browser compatibility - // noinspection JSUnresolvedVariable - var matchesFunction = elt.matches || elt.matchesSelector || elt.msMatchesSelector || elt.mozMatchesSelector || elt.webkitMatchesSelector || elt.oMatchesSelector; - return matchesFunction && matchesFunction.call(elt, selector); - } - - /** - * @param {string} str - * @returns {string} - */ - function getStartTag(str) { - var tagMatcher = /<([a-z][^\/\0>\x20\t\r\n\f]*)/i - var match = tagMatcher.exec( str ); - if (match) { - return match[1].toLowerCase(); - } else { - return ""; - } - } - - /** - * - * @param {string} resp - * @param {number} depth - * @returns {Element} - */ - function parseHTML(resp, depth) { - var parser = new DOMParser(); - var responseDoc = parser.parseFromString(resp, "text/html"); - - /** @type {Element} */ - var responseNode = responseDoc.body; - while (depth > 0) { - depth--; - // @ts-ignore - responseNode = responseNode.firstChild; - } - if (responseNode == null) { - // @ts-ignore - responseNode = getDocument().createDocumentFragment(); - } - return responseNode; - } - - function aFullPageResponse(resp) { - return /", 0); - // @ts-ignore type mismatch between DocumentFragment and Element. - // TODO: Are these close enough for htmx to use interchangeably? - var fragmentContent = fragment.querySelector('template').content; - if (htmx.config.allowScriptTags) { - // if there is a nonce set up, set it on the new script tags - forEach(fragmentContent.querySelectorAll("script"), function (script) { - if (htmx.config.inlineScriptNonce) { - script.nonce = htmx.config.inlineScriptNonce; - } - // mark as executed due to template insertion semantics on all browsers except firefox fml - script.htmxExecuted = navigator.userAgent.indexOf("Firefox") === -1; - }) - } else { - forEach(fragmentContent.querySelectorAll("script"), function (script) { - // remove all script tags if scripts are disabled - removeElement(script); - }) - } - return fragmentContent; - } - switch (startTag) { - case "thead": - case "tbody": - case "tfoot": - case "colgroup": - case "caption": - return parseHTML("" + content + "
    ", 1); - case "col": - return parseHTML("" + content + "
    ", 2); - case "tr": - return parseHTML("" + content + "
    ", 2); - case "td": - case "th": - return parseHTML("" + content + "
    ", 3); - case "script": - case "style": - return parseHTML("
    " + content + "
    ", 1); - default: - return parseHTML(content, 0); - } - } - - /** - * @param {Function} func - */ - function maybeCall(func){ - if(func) { - func(); - } - } - - /** - * @param {any} o - * @param {string} type - * @returns - */ - function isType(o, type) { - return Object.prototype.toString.call(o) === "[object " + type + "]"; - } - - /** - * @param {*} o - * @returns {o is Function} - */ - function isFunction(o) { - return isType(o, "Function"); - } - - /** - * @param {*} o - * @returns {o is Object} - */ - function isRawObject(o) { - return isType(o, "Object"); - } - - /** - * getInternalData retrieves "private" data stored by htmx within an element - * @param {HTMLElement} elt - * @returns {*} - */ - function getInternalData(elt) { - var dataProp = 'htmx-internal-data'; - var data = elt[dataProp]; - if (!data) { - data = elt[dataProp] = {}; - } - return data; - } - - /** - * toArray converts an ArrayLike object into a real array. - * @param {ArrayLike} arr - * @returns {any[]} - */ - function toArray(arr) { - var returnArr = []; - if (arr) { - for (var i = 0; i < arr.length; i++) { - returnArr.push(arr[i]); - } - } - return returnArr - } - - function forEach(arr, func) { - if (arr) { - for (var i = 0; i < arr.length; i++) { - func(arr[i]); - } - } - } - - function isScrolledIntoView(el) { - var rect = el.getBoundingClientRect(); - var elemTop = rect.top; - var elemBottom = rect.bottom; - return elemTop < window.innerHeight && elemBottom >= 0; - } - - function bodyContains(elt) { - // IE Fix - if (elt.getRootNode && elt.getRootNode() instanceof window.ShadowRoot) { - return getDocument().body.contains(elt.getRootNode().host); - } else { - return getDocument().body.contains(elt); - } - } - - function splitOnWhitespace(trigger) { - return trigger.trim().split(/\s+/); - } - - /** - * mergeObjects takes all of the keys from - * obj2 and duplicates them into obj1 - * @param {Object} obj1 - * @param {Object} obj2 - * @returns {Object} - */ - function mergeObjects(obj1, obj2) { - for (var key in obj2) { - if (obj2.hasOwnProperty(key)) { - obj1[key] = obj2[key]; - } - } - return obj1; - } - - function parseJSON(jString) { - try { - return JSON.parse(jString); - } catch(error) { - logError(error); - return null; - } - } - - function canAccessLocalStorage() { - var test = 'htmx:localStorageTest'; - try { - localStorage.setItem(test, test); - localStorage.removeItem(test); - return true; - } catch(e) { - return false; - } - } - - function normalizePath(path) { - try { - var url = new URL(path); - if (url) { - path = url.pathname + url.search; - } - // remove trailing slash, unless index page - if (!(/^\/$/.test(path))) { - path = path.replace(/\/+$/, ''); - } - return path; - } catch (e) { - // be kind to IE11, which doesn't support URL() - return path; - } - } - - //========================================================================================== - // public API - //========================================================================================== - - function internalEval(str){ - return maybeEval(getDocument().body, function () { - return eval(str); - }); - } - - function onLoadHelper(callback) { - var value = htmx.on("htmx:load", function(evt) { - callback(evt.detail.elt); - }); - return value; - } - - function logAll(){ - htmx.logger = function(elt, event, data) { - if(console) { - console.log(event, elt, data); - } - } - } - - function logNone() { - htmx.logger = null - } - - function find(eltOrSelector, selector) { - if (selector) { - return eltOrSelector.querySelector(selector); - } else { - return find(getDocument(), eltOrSelector); - } - } - - function findAll(eltOrSelector, selector) { - if (selector) { - return eltOrSelector.querySelectorAll(selector); - } else { - return findAll(getDocument(), eltOrSelector); - } - } - - function removeElement(elt, delay) { - elt = resolveTarget(elt); - if (delay) { - setTimeout(function(){ - removeElement(elt); - elt = null; - }, delay); - } else { - elt.parentElement.removeChild(elt); - } - } - - function addClassToElement(elt, clazz, delay) { - elt = resolveTarget(elt); - if (delay) { - setTimeout(function(){ - addClassToElement(elt, clazz); - elt = null; - }, delay); - } else { - elt.classList && elt.classList.add(clazz); - } - } - - function removeClassFromElement(elt, clazz, delay) { - elt = resolveTarget(elt); - if (delay) { - setTimeout(function(){ - removeClassFromElement(elt, clazz); - elt = null; - }, delay); - } else { - if (elt.classList) { - elt.classList.remove(clazz); - // if there are no classes left, remove the class attribute - if (elt.classList.length === 0) { - elt.removeAttribute("class"); - } - } - } - } - - function toggleClassOnElement(elt, clazz) { - elt = resolveTarget(elt); - elt.classList.toggle(clazz); - } - - function takeClassForElement(elt, clazz) { - elt = resolveTarget(elt); - forEach(elt.parentElement.children, function(child){ - removeClassFromElement(child, clazz); - }) - addClassToElement(elt, clazz); - } - - function closest(elt, selector) { - elt = resolveTarget(elt); - if (elt.closest) { - return elt.closest(selector); - } else { - // TODO remove when IE goes away - do{ - if (elt == null || matches(elt, selector)){ - return elt; - } - } - while (elt = elt && parentElt(elt)); - return null; - } - } - - function startsWith(str, prefix) { - return str.substring(0, prefix.length) === prefix - } - - function endsWith(str, suffix) { - return str.substring(str.length - suffix.length) === suffix - } - - function normalizeSelector(selector) { - var trimmedSelector = selector.trim(); - if (startsWith(trimmedSelector, "<") && endsWith(trimmedSelector, "/>")) { - return trimmedSelector.substring(1, trimmedSelector.length - 2); - } else { - return trimmedSelector; - } - } - - function querySelectorAllExt(elt, selector) { - if (selector.indexOf("closest ") === 0) { - return [closest(elt, normalizeSelector(selector.substr(8)))]; - } else if (selector.indexOf("find ") === 0) { - return [find(elt, normalizeSelector(selector.substr(5)))]; - } else if (selector === "next") { - return [elt.nextElementSibling] - } else if (selector.indexOf("next ") === 0) { - return [scanForwardQuery(elt, normalizeSelector(selector.substr(5)))]; - } else if (selector === "previous") { - return [elt.previousElementSibling] - } else if (selector.indexOf("previous ") === 0) { - return [scanBackwardsQuery(elt, normalizeSelector(selector.substr(9)))]; - } else if (selector === 'document') { - return [document]; - } else if (selector === 'window') { - return [window]; - } else if (selector === 'body') { - return [document.body]; - } else { - return getDocument().querySelectorAll(normalizeSelector(selector)); - } - } - - var scanForwardQuery = function(start, match) { - var results = getDocument().querySelectorAll(match); - for (var i = 0; i < results.length; i++) { - var elt = results[i]; - if (elt.compareDocumentPosition(start) === Node.DOCUMENT_POSITION_PRECEDING) { - return elt; - } - } - } - - var scanBackwardsQuery = function(start, match) { - var results = getDocument().querySelectorAll(match); - for (var i = results.length - 1; i >= 0; i--) { - var elt = results[i]; - if (elt.compareDocumentPosition(start) === Node.DOCUMENT_POSITION_FOLLOWING) { - return elt; - } - } - } - - function querySelectorExt(eltOrSelector, selector) { - if (selector) { - return querySelectorAllExt(eltOrSelector, selector)[0]; - } else { - return querySelectorAllExt(getDocument().body, eltOrSelector)[0]; - } - } - - function resolveTarget(arg2) { - if (isType(arg2, 'String')) { - return find(arg2); - } else { - return arg2; - } - } - - function processEventArgs(arg1, arg2, arg3) { - if (isFunction(arg2)) { - return { - target: getDocument().body, - event: arg1, - listener: arg2 - } - } else { - return { - target: resolveTarget(arg1), - event: arg2, - listener: arg3 - } - } - - } - - function addEventListenerImpl(arg1, arg2, arg3) { - ready(function(){ - var eventArgs = processEventArgs(arg1, arg2, arg3); - eventArgs.target.addEventListener(eventArgs.event, eventArgs.listener); - }) - var b = isFunction(arg2); - return b ? arg2 : arg3; - } - - function removeEventListenerImpl(arg1, arg2, arg3) { - ready(function(){ - var eventArgs = processEventArgs(arg1, arg2, arg3); - eventArgs.target.removeEventListener(eventArgs.event, eventArgs.listener); - }) - return isFunction(arg2) ? arg2 : arg3; - } - - //==================================================================== - // Node processing - //==================================================================== - - var DUMMY_ELT = getDocument().createElement("output"); // dummy element for bad selectors - function findAttributeTargets(elt, attrName) { - var attrTarget = getClosestAttributeValue(elt, attrName); - if (attrTarget) { - if (attrTarget === "this") { - return [findThisElement(elt, attrName)]; - } else { - var result = querySelectorAllExt(elt, attrTarget); - if (result.length === 0) { - logError('The selector "' + attrTarget + '" on ' + attrName + " returned no matches!"); - return [DUMMY_ELT] - } else { - return result; - } - } - } - } - - function findThisElement(elt, attribute){ - return getClosestMatch(elt, function (elt) { - return getAttributeValue(elt, attribute) != null; - }) - } - - function getTarget(elt) { - var targetStr = getClosestAttributeValue(elt, "hx-target"); - if (targetStr) { - if (targetStr === "this") { - return findThisElement(elt,'hx-target'); - } else { - return querySelectorExt(elt, targetStr) - } - } else { - var data = getInternalData(elt); - if (data.boosted) { - return getDocument().body; - } else { - return elt; - } - } - } - - function shouldSettleAttribute(name) { - var attributesToSettle = htmx.config.attributesToSettle; - for (var i = 0; i < attributesToSettle.length; i++) { - if (name === attributesToSettle[i]) { - return true; - } - } - return false; - } - - function cloneAttributes(mergeTo, mergeFrom) { - forEach(mergeTo.attributes, function (attr) { - if (!mergeFrom.hasAttribute(attr.name) && shouldSettleAttribute(attr.name)) { - mergeTo.removeAttribute(attr.name) - } - }); - forEach(mergeFrom.attributes, function (attr) { - if (shouldSettleAttribute(attr.name)) { - mergeTo.setAttribute(attr.name, attr.value); - } - }); - } - - function isInlineSwap(swapStyle, target) { - var extensions = getExtensions(target); - for (var i = 0; i < extensions.length; i++) { - var extension = extensions[i]; - try { - if (extension.isInlineSwap(swapStyle)) { - return true; - } - } catch(e) { - logError(e); - } - } - return swapStyle === "outerHTML"; - } - - /** - * - * @param {string} oobValue - * @param {HTMLElement} oobElement - * @param {*} settleInfo - * @returns - */ - function oobSwap(oobValue, oobElement, settleInfo) { - var selector = "#" + getRawAttribute(oobElement, "id"); - var swapStyle = "outerHTML"; - if (oobValue === "true") { - // do nothing - } else if (oobValue.indexOf(":") > 0) { - swapStyle = oobValue.substr(0, oobValue.indexOf(":")); - selector = oobValue.substr(oobValue.indexOf(":") + 1, oobValue.length); - } else { - swapStyle = oobValue; - } - - var targets = getDocument().querySelectorAll(selector); - if (targets) { - forEach( - targets, - function (target) { - var fragment; - var oobElementClone = oobElement.cloneNode(true); - fragment = getDocument().createDocumentFragment(); - fragment.appendChild(oobElementClone); - if (!isInlineSwap(swapStyle, target)) { - fragment = oobElementClone; // if this is not an inline swap, we use the content of the node, not the node itself - } - - var beforeSwapDetails = {shouldSwap: true, target: target, fragment:fragment }; - if (!triggerEvent(target, 'htmx:oobBeforeSwap', beforeSwapDetails)) return; - - target = beforeSwapDetails.target; // allow re-targeting - if (beforeSwapDetails['shouldSwap']){ - swap(swapStyle, target, target, fragment, settleInfo); - } - forEach(settleInfo.elts, function (elt) { - triggerEvent(elt, 'htmx:oobAfterSwap', beforeSwapDetails); - }); - } - ); - oobElement.parentNode.removeChild(oobElement); - } else { - oobElement.parentNode.removeChild(oobElement); - triggerErrorEvent(getDocument().body, "htmx:oobErrorNoTarget", {content: oobElement}); - } - return oobValue; - } - - function handleOutOfBandSwaps(elt, fragment, settleInfo) { - var oobSelects = getClosestAttributeValue(elt, "hx-select-oob"); - if (oobSelects) { - var oobSelectValues = oobSelects.split(","); - for (var i = 0; i < oobSelectValues.length; i++) { - var oobSelectValue = oobSelectValues[i].split(":", 2); - var id = oobSelectValue[0].trim(); - if (id.indexOf("#") === 0) { - id = id.substring(1); - } - var oobValue = oobSelectValue[1] || "true"; - var oobElement = fragment.querySelector("#" + id); - if (oobElement) { - oobSwap(oobValue, oobElement, settleInfo); - } - } - } - forEach(findAll(fragment, '[hx-swap-oob], [data-hx-swap-oob]'), function (oobElement) { - var oobValue = getAttributeValue(oobElement, "hx-swap-oob"); - if (oobValue != null) { - oobSwap(oobValue, oobElement, settleInfo); - } - }); - } - - function handlePreservedElements(fragment) { - forEach(findAll(fragment, '[hx-preserve], [data-hx-preserve]'), function (preservedElt) { - var id = getAttributeValue(preservedElt, "id"); - var oldElt = getDocument().getElementById(id); - if (oldElt != null) { - preservedElt.parentNode.replaceChild(oldElt, preservedElt); - } - }); - } - - function handleAttributes(parentNode, fragment, settleInfo) { - forEach(fragment.querySelectorAll("[id]"), function (newNode) { - var id = getRawAttribute(newNode, "id") - if (id && id.length > 0) { - var normalizedId = id.replace("'", "\\'"); - var normalizedTag = newNode.tagName.replace(':', '\\:'); - var oldNode = parentNode.querySelector(normalizedTag + "[id='" + normalizedId + "']"); - if (oldNode && oldNode !== parentNode) { - var newAttributes = newNode.cloneNode(); - cloneAttributes(newNode, oldNode); - settleInfo.tasks.push(function () { - cloneAttributes(newNode, newAttributes); - }); - } - } - }); - } - - function makeAjaxLoadTask(child) { - return function () { - removeClassFromElement(child, htmx.config.addedClass); - processNode(child); - processScripts(child); - processFocus(child) - triggerEvent(child, 'htmx:load'); - }; - } - - function processFocus(child) { - var autofocus = "[autofocus]"; - var autoFocusedElt = matches(child, autofocus) ? child : child.querySelector(autofocus) - if (autoFocusedElt != null) { - autoFocusedElt.focus(); - } - } - - function insertNodesBefore(parentNode, insertBefore, fragment, settleInfo) { - handleAttributes(parentNode, fragment, settleInfo); - while(fragment.childNodes.length > 0){ - var child = fragment.firstChild; - addClassToElement(child, htmx.config.addedClass); - parentNode.insertBefore(child, insertBefore); - if (child.nodeType !== Node.TEXT_NODE && child.nodeType !== Node.COMMENT_NODE) { - settleInfo.tasks.push(makeAjaxLoadTask(child)); - } - } - } - - // based on https://gist.github.com/hyamamoto/fd435505d29ebfa3d9716fd2be8d42f0, - // derived from Java's string hashcode implementation - function stringHash(string, hash) { - var char = 0; - while (char < string.length){ - hash = (hash << 5) - hash + string.charCodeAt(char++) | 0; // bitwise or ensures we have a 32-bit int - } - return hash; - } - - function attributeHash(elt) { - var hash = 0; - // IE fix - if (elt.attributes) { - for (var i = 0; i < elt.attributes.length; i++) { - var attribute = elt.attributes[i]; - if(attribute.value){ // only include attributes w/ actual values (empty is same as non-existent) - hash = stringHash(attribute.name, hash); - hash = stringHash(attribute.value, hash); - } - } - } - return hash; - } - - function deInitOnHandlers(elt) { - var internalData = getInternalData(elt); - if (internalData.onHandlers) { - for (var i = 0; i < internalData.onHandlers.length; i++) { - const handlerInfo = internalData.onHandlers[i]; - elt.removeEventListener(handlerInfo.event, handlerInfo.listener); - } - delete internalData.onHandlers - } - } - - function deInitNode(element) { - var internalData = getInternalData(element); - if (internalData.timeout) { - clearTimeout(internalData.timeout); - } - if (internalData.webSocket) { - internalData.webSocket.close(); - } - if (internalData.sseEventSource) { - internalData.sseEventSource.close(); - } - if (internalData.listenerInfos) { - forEach(internalData.listenerInfos, function (info) { - if (info.on) { - info.on.removeEventListener(info.trigger, info.listener); - } - }); - } - deInitOnHandlers(element); - forEach(Object.keys(internalData), function(key) { delete internalData[key] }); - } - - function cleanUpElement(element) { - triggerEvent(element, "htmx:beforeCleanupElement") - deInitNode(element); - if (element.children) { // IE - forEach(element.children, function(child) { cleanUpElement(child) }); - } - } - - function swapOuterHTML(target, fragment, settleInfo) { - if (target.tagName === "BODY") { - return swapInnerHTML(target, fragment, settleInfo); - } else { - // @type {HTMLElement} - var newElt - var eltBeforeNewContent = target.previousSibling; - insertNodesBefore(parentElt(target), target, fragment, settleInfo); - if (eltBeforeNewContent == null) { - newElt = parentElt(target).firstChild; - } else { - newElt = eltBeforeNewContent.nextSibling; - } - settleInfo.elts = settleInfo.elts.filter(function(e) { return e != target }); - while(newElt && newElt !== target) { - if (newElt.nodeType === Node.ELEMENT_NODE) { - settleInfo.elts.push(newElt); - } - newElt = newElt.nextElementSibling; - } - cleanUpElement(target); - parentElt(target).removeChild(target); - } - } - - function swapAfterBegin(target, fragment, settleInfo) { - return insertNodesBefore(target, target.firstChild, fragment, settleInfo); - } - - function swapBeforeBegin(target, fragment, settleInfo) { - return insertNodesBefore(parentElt(target), target, fragment, settleInfo); - } - - function swapBeforeEnd(target, fragment, settleInfo) { - return insertNodesBefore(target, null, fragment, settleInfo); - } - - function swapAfterEnd(target, fragment, settleInfo) { - return insertNodesBefore(parentElt(target), target.nextSibling, fragment, settleInfo); - } - function swapDelete(target, fragment, settleInfo) { - cleanUpElement(target); - return parentElt(target).removeChild(target); - } - - function swapInnerHTML(target, fragment, settleInfo) { - var firstChild = target.firstChild; - insertNodesBefore(target, firstChild, fragment, settleInfo); - if (firstChild) { - while (firstChild.nextSibling) { - cleanUpElement(firstChild.nextSibling) - target.removeChild(firstChild.nextSibling); - } - cleanUpElement(firstChild) - target.removeChild(firstChild); - } - } - - function maybeSelectFromResponse(elt, fragment, selectOverride) { - var selector = selectOverride || getClosestAttributeValue(elt, "hx-select"); - if (selector) { - var newFragment = getDocument().createDocumentFragment(); - forEach(fragment.querySelectorAll(selector), function (node) { - newFragment.appendChild(node); - }); - fragment = newFragment; - } - return fragment; - } - - function swap(swapStyle, elt, target, fragment, settleInfo) { - switch (swapStyle) { - case "none": - return; - case "outerHTML": - swapOuterHTML(target, fragment, settleInfo); - return; - case "afterbegin": - swapAfterBegin(target, fragment, settleInfo); - return; - case "beforebegin": - swapBeforeBegin(target, fragment, settleInfo); - return; - case "beforeend": - swapBeforeEnd(target, fragment, settleInfo); - return; - case "afterend": - swapAfterEnd(target, fragment, settleInfo); - return; - case "delete": - swapDelete(target, fragment, settleInfo); - return; - default: - var extensions = getExtensions(elt); - for (var i = 0; i < extensions.length; i++) { - var ext = extensions[i]; - try { - var newElements = ext.handleSwap(swapStyle, target, fragment, settleInfo); - if (newElements) { - if (typeof newElements.length !== 'undefined') { - // if handleSwap returns an array (like) of elements, we handle them - for (var j = 0; j < newElements.length; j++) { - var child = newElements[j]; - if (child.nodeType !== Node.TEXT_NODE && child.nodeType !== Node.COMMENT_NODE) { - settleInfo.tasks.push(makeAjaxLoadTask(child)); - } - } - } - return; - } - } catch (e) { - logError(e); - } - } - if (swapStyle === "innerHTML") { - swapInnerHTML(target, fragment, settleInfo); - } else { - swap(htmx.config.defaultSwapStyle, elt, target, fragment, settleInfo); - } - } - } - - function findTitle(content) { - if (content.indexOf(' -1) { - var contentWithSvgsRemoved = content.replace(SVG_TAGS_REGEX, ''); - var result = contentWithSvgsRemoved.match(TITLE_TAG_REGEX); - if (result) { - return result[2]; - } - } - } - - function selectAndSwap(swapStyle, target, elt, responseText, settleInfo, selectOverride) { - settleInfo.title = findTitle(responseText); - var fragment = makeFragment(responseText); - if (fragment) { - handleOutOfBandSwaps(elt, fragment, settleInfo); - fragment = maybeSelectFromResponse(elt, fragment, selectOverride); - handlePreservedElements(fragment); - return swap(swapStyle, elt, target, fragment, settleInfo); - } - } - - function handleTrigger(xhr, header, elt) { - var triggerBody = xhr.getResponseHeader(header); - if (triggerBody.indexOf("{") === 0) { - var triggers = parseJSON(triggerBody); - for (var eventName in triggers) { - if (triggers.hasOwnProperty(eventName)) { - var detail = triggers[eventName]; - if (!isRawObject(detail)) { - detail = {"value": detail} - } - triggerEvent(elt, eventName, detail); - } - } - } else { - var eventNames = triggerBody.split(",") - for (var i = 0; i < eventNames.length; i++) { - triggerEvent(elt, eventNames[i].trim(), []); - } - } - } - - var WHITESPACE = /\s/; - var WHITESPACE_OR_COMMA = /[\s,]/; - var SYMBOL_START = /[_$a-zA-Z]/; - var SYMBOL_CONT = /[_$a-zA-Z0-9]/; - var STRINGISH_START = ['"', "'", "/"]; - var NOT_WHITESPACE = /[^\s]/; - var COMBINED_SELECTOR_START = /[{(]/; - var COMBINED_SELECTOR_END = /[})]/; - function tokenizeString(str) { - var tokens = []; - var position = 0; - while (position < str.length) { - if(SYMBOL_START.exec(str.charAt(position))) { - var startPosition = position; - while (SYMBOL_CONT.exec(str.charAt(position + 1))) { - position++; - } - tokens.push(str.substr(startPosition, position - startPosition + 1)); - } else if (STRINGISH_START.indexOf(str.charAt(position)) !== -1) { - var startChar = str.charAt(position); - var startPosition = position; - position++; - while (position < str.length && str.charAt(position) !== startChar ) { - if (str.charAt(position) === "\\") { - position++; - } - position++; - } - tokens.push(str.substr(startPosition, position - startPosition + 1)); - } else { - var symbol = str.charAt(position); - tokens.push(symbol); - } - position++; - } - return tokens; - } - - function isPossibleRelativeReference(token, last, paramName) { - return SYMBOL_START.exec(token.charAt(0)) && - token !== "true" && - token !== "false" && - token !== "this" && - token !== paramName && - last !== "."; - } - - function maybeGenerateConditional(elt, tokens, paramName) { - if (tokens[0] === '[') { - tokens.shift(); - var bracketCount = 1; - var conditionalSource = " return (function(" + paramName + "){ return ("; - var last = null; - while (tokens.length > 0) { - var token = tokens[0]; - if (token === "]") { - bracketCount--; - if (bracketCount === 0) { - if (last === null) { - conditionalSource = conditionalSource + "true"; - } - tokens.shift(); - conditionalSource += ")})"; - try { - var conditionFunction = maybeEval(elt,function () { - return Function(conditionalSource)(); - }, - function(){return true}) - conditionFunction.source = conditionalSource; - return conditionFunction; - } catch (e) { - triggerErrorEvent(getDocument().body, "htmx:syntax:error", {error:e, source:conditionalSource}) - return null; - } - } - } else if (token === "[") { - bracketCount++; - } - if (isPossibleRelativeReference(token, last, paramName)) { - conditionalSource += "((" + paramName + "." + token + ") ? (" + paramName + "." + token + ") : (window." + token + "))"; - } else { - conditionalSource = conditionalSource + token; - } - last = tokens.shift(); - } - } - } - - function consumeUntil(tokens, match) { - var result = ""; - while (tokens.length > 0 && !match.test(tokens[0])) { - result += tokens.shift(); - } - return result; - } - - function consumeCSSSelector(tokens) { - var result; - if (tokens.length > 0 && COMBINED_SELECTOR_START.test(tokens[0])) { - tokens.shift(); - result = consumeUntil(tokens, COMBINED_SELECTOR_END).trim(); - tokens.shift(); - } else { - result = consumeUntil(tokens, WHITESPACE_OR_COMMA); - } - return result; - } - - var INPUT_SELECTOR = 'input, textarea, select'; - - /** - * @param {HTMLElement} elt - * @param {string} explicitTrigger - * @param {cache} cache for trigger specs - * @returns {import("./htmx").HtmxTriggerSpecification[]} - */ - function parseAndCacheTrigger(elt, explicitTrigger, cache) { - var triggerSpecs = []; - var tokens = tokenizeString(explicitTrigger); - do { - consumeUntil(tokens, NOT_WHITESPACE); - var initialLength = tokens.length; - var trigger = consumeUntil(tokens, /[,\[\s]/); - if (trigger !== "") { - if (trigger === "every") { - var every = {trigger: 'every'}; - consumeUntil(tokens, NOT_WHITESPACE); - every.pollInterval = parseInterval(consumeUntil(tokens, /[,\[\s]/)); - consumeUntil(tokens, NOT_WHITESPACE); - var eventFilter = maybeGenerateConditional(elt, tokens, "event"); - if (eventFilter) { - every.eventFilter = eventFilter; - } - triggerSpecs.push(every); - } else if (trigger.indexOf("sse:") === 0) { - triggerSpecs.push({trigger: 'sse', sseEvent: trigger.substr(4)}); - } else { - var triggerSpec = {trigger: trigger}; - var eventFilter = maybeGenerateConditional(elt, tokens, "event"); - if (eventFilter) { - triggerSpec.eventFilter = eventFilter; - } - while (tokens.length > 0 && tokens[0] !== ",") { - consumeUntil(tokens, NOT_WHITESPACE) - var token = tokens.shift(); - if (token === "changed") { - triggerSpec.changed = true; - } else if (token === "once") { - triggerSpec.once = true; - } else if (token === "consume") { - triggerSpec.consume = true; - } else if (token === "delay" && tokens[0] === ":") { - tokens.shift(); - triggerSpec.delay = parseInterval(consumeUntil(tokens, WHITESPACE_OR_COMMA)); - } else if (token === "from" && tokens[0] === ":") { - tokens.shift(); - if (COMBINED_SELECTOR_START.test(tokens[0])) { - var from_arg = consumeCSSSelector(tokens); - } else { - var from_arg = consumeUntil(tokens, WHITESPACE_OR_COMMA); - if (from_arg === "closest" || from_arg === "find" || from_arg === "next" || from_arg === "previous") { - tokens.shift(); - var selector = consumeCSSSelector(tokens); - // `next` and `previous` allow a selector-less syntax - if (selector.length > 0) { - from_arg += " " + selector; - } - } - } - triggerSpec.from = from_arg; - } else if (token === "target" && tokens[0] === ":") { - tokens.shift(); - triggerSpec.target = consumeCSSSelector(tokens); - } else if (token === "throttle" && tokens[0] === ":") { - tokens.shift(); - triggerSpec.throttle = parseInterval(consumeUntil(tokens, WHITESPACE_OR_COMMA)); - } else if (token === "queue" && tokens[0] === ":") { - tokens.shift(); - triggerSpec.queue = consumeUntil(tokens, WHITESPACE_OR_COMMA); - } else if (token === "root" && tokens[0] === ":") { - tokens.shift(); - triggerSpec[token] = consumeCSSSelector(tokens); - } else if (token === "threshold" && tokens[0] === ":") { - tokens.shift(); - triggerSpec[token] = consumeUntil(tokens, WHITESPACE_OR_COMMA); - } else { - triggerErrorEvent(elt, "htmx:syntax:error", {token:tokens.shift()}); - } - } - triggerSpecs.push(triggerSpec); - } - } - if (tokens.length === initialLength) { - triggerErrorEvent(elt, "htmx:syntax:error", {token:tokens.shift()}); - } - consumeUntil(tokens, NOT_WHITESPACE); - } while (tokens[0] === "," && tokens.shift()) - if (cache) { - cache[explicitTrigger] = triggerSpecs - } - return triggerSpecs - } - - /** - * @param {HTMLElement} elt - * @returns {import("./htmx").HtmxTriggerSpecification[]} - */ - function getTriggerSpecs(elt) { - var explicitTrigger = getAttributeValue(elt, 'hx-trigger'); - var triggerSpecs = []; - if (explicitTrigger) { - var cache = htmx.config.triggerSpecsCache - triggerSpecs = (cache && cache[explicitTrigger]) || parseAndCacheTrigger(elt, explicitTrigger, cache) - } - - if (triggerSpecs.length > 0) { - return triggerSpecs; - } else if (matches(elt, 'form')) { - return [{trigger: 'submit'}]; - } else if (matches(elt, 'input[type="button"], input[type="submit"]')){ - return [{trigger: 'click'}]; - } else if (matches(elt, INPUT_SELECTOR)) { - return [{trigger: 'change'}]; - } else { - return [{trigger: 'click'}]; - } - } - - function cancelPolling(elt) { - getInternalData(elt).cancelled = true; - } - - function processPolling(elt, handler, spec) { - var nodeData = getInternalData(elt); - nodeData.timeout = setTimeout(function () { - if (bodyContains(elt) && nodeData.cancelled !== true) { - if (!maybeFilterEvent(spec, elt, makeEvent('hx:poll:trigger', { - triggerSpec: spec, - target: elt - }))) { - handler(elt); - } - processPolling(elt, handler, spec); - } - }, spec.pollInterval); - } - - function isLocalLink(elt) { - return location.hostname === elt.hostname && - getRawAttribute(elt,'href') && - getRawAttribute(elt,'href').indexOf("#") !== 0; - } - - function boostElement(elt, nodeData, triggerSpecs) { - if ((elt.tagName === "A" && isLocalLink(elt) && (elt.target === "" || elt.target === "_self")) || elt.tagName === "FORM") { - nodeData.boosted = true; - var verb, path; - if (elt.tagName === "A") { - verb = "get"; - path = getRawAttribute(elt, 'href') - } else { - var rawAttribute = getRawAttribute(elt, "method"); - verb = rawAttribute ? rawAttribute.toLowerCase() : "get"; - if (verb === "get") { - } - path = getRawAttribute(elt, 'action'); - } - triggerSpecs.forEach(function(triggerSpec) { - addEventListener(elt, function(elt, evt) { - if (closest(elt, htmx.config.disableSelector)) { - cleanUpElement(elt) - return - } - issueAjaxRequest(verb, path, elt, evt) - }, nodeData, triggerSpec, true); - }); - } - } - - /** - * - * @param {Event} evt - * @param {HTMLElement} elt - * @returns - */ - function shouldCancel(evt, elt) { - if (evt.type === "submit" || evt.type === "click") { - if (elt.tagName === "FORM") { - return true; - } - if (matches(elt, 'input[type="submit"], button') && closest(elt, 'form') !== null) { - return true; - } - if (elt.tagName === "A" && elt.href && - (elt.getAttribute('href') === '#' || elt.getAttribute('href').indexOf("#") !== 0)) { - return true; - } - } - return false; - } - - function ignoreBoostedAnchorCtrlClick(elt, evt) { - return getInternalData(elt).boosted && elt.tagName === "A" && evt.type === "click" && (evt.ctrlKey || evt.metaKey); - } - - function maybeFilterEvent(triggerSpec, elt, evt) { - var eventFilter = triggerSpec.eventFilter; - if(eventFilter){ - try { - return eventFilter.call(elt, evt) !== true; - } catch(e) { - triggerErrorEvent(getDocument().body, "htmx:eventFilter:error", {error: e, source:eventFilter.source}); - return true; - } - } - return false; - } - - function addEventListener(elt, handler, nodeData, triggerSpec, explicitCancel) { - var elementData = getInternalData(elt); - var eltsToListenOn; - if (triggerSpec.from) { - eltsToListenOn = querySelectorAllExt(elt, triggerSpec.from); - } else { - eltsToListenOn = [elt]; - } - // store the initial values of the elements, so we can tell if they change - if (triggerSpec.changed) { - eltsToListenOn.forEach(function (eltToListenOn) { - var eltToListenOnData = getInternalData(eltToListenOn); - eltToListenOnData.lastValue = eltToListenOn.value; - }) - } - forEach(eltsToListenOn, function (eltToListenOn) { - var eventListener = function (evt) { - if (!bodyContains(elt)) { - eltToListenOn.removeEventListener(triggerSpec.trigger, eventListener); - return; - } - if (ignoreBoostedAnchorCtrlClick(elt, evt)) { - return; - } - if (explicitCancel || shouldCancel(evt, elt)) { - evt.preventDefault(); - } - if (maybeFilterEvent(triggerSpec, elt, evt)) { - return; - } - var eventData = getInternalData(evt); - eventData.triggerSpec = triggerSpec; - if (eventData.handledFor == null) { - eventData.handledFor = []; - } - if (eventData.handledFor.indexOf(elt) < 0) { - eventData.handledFor.push(elt); - if (triggerSpec.consume) { - evt.stopPropagation(); - } - if (triggerSpec.target && evt.target) { - if (!matches(evt.target, triggerSpec.target)) { - return; - } - } - if (triggerSpec.once) { - if (elementData.triggeredOnce) { - return; - } else { - elementData.triggeredOnce = true; - } - } - if (triggerSpec.changed) { - var eltToListenOnData = getInternalData(eltToListenOn) - if (eltToListenOnData.lastValue === eltToListenOn.value) { - return; - } - eltToListenOnData.lastValue = eltToListenOn.value - } - if (elementData.delayed) { - clearTimeout(elementData.delayed); - } - if (elementData.throttle) { - return; - } - - if (triggerSpec.throttle > 0) { - if (!elementData.throttle) { - handler(elt, evt); - elementData.throttle = setTimeout(function () { - elementData.throttle = null; - }, triggerSpec.throttle); - } - } else if (triggerSpec.delay > 0) { - elementData.delayed = setTimeout(function() { handler(elt, evt) }, triggerSpec.delay); - } else { - triggerEvent(elt, 'htmx:trigger') - handler(elt, evt); - } - } - }; - if (nodeData.listenerInfos == null) { - nodeData.listenerInfos = []; - } - nodeData.listenerInfos.push({ - trigger: triggerSpec.trigger, - listener: eventListener, - on: eltToListenOn - }) - eltToListenOn.addEventListener(triggerSpec.trigger, eventListener); - }); - } - - var windowIsScrolling = false // used by initScrollHandler - var scrollHandler = null; - function initScrollHandler() { - if (!scrollHandler) { - scrollHandler = function() { - windowIsScrolling = true - }; - window.addEventListener("scroll", scrollHandler) - setInterval(function() { - if (windowIsScrolling) { - windowIsScrolling = false; - forEach(getDocument().querySelectorAll("[hx-trigger='revealed'],[data-hx-trigger='revealed']"), function (elt) { - maybeReveal(elt); - }) - } - }, 200); - } - } - - function maybeReveal(elt) { - if (!hasAttribute(elt,'data-hx-revealed') && isScrolledIntoView(elt)) { - elt.setAttribute('data-hx-revealed', 'true'); - var nodeData = getInternalData(elt); - if (nodeData.initHash) { - triggerEvent(elt, 'revealed'); - } else { - // if the node isn't initialized, wait for it before triggering the request - elt.addEventListener("htmx:afterProcessNode", function(evt) { triggerEvent(elt, 'revealed') }, {once: true}); - } - } - } - - //==================================================================== - // Web Sockets - //==================================================================== - - function processWebSocketInfo(elt, nodeData, info) { - var values = splitOnWhitespace(info); - for (var i = 0; i < values.length; i++) { - var value = values[i].split(/:(.+)/); - if (value[0] === "connect") { - ensureWebSocket(elt, value[1], 0); - } - if (value[0] === "send") { - processWebSocketSend(elt); - } - } - } - - function ensureWebSocket(elt, wssSource, retryCount) { - if (!bodyContains(elt)) { - return; // stop ensuring websocket connection when socket bearing element ceases to exist - } - - if (wssSource.indexOf("/") == 0) { // complete absolute paths only - var base_part = location.hostname + (location.port ? ':'+location.port: ''); - if (location.protocol == 'https:') { - wssSource = "wss://" + base_part + wssSource; - } else if (location.protocol == 'http:') { - wssSource = "ws://" + base_part + wssSource; - } - } - var socket = htmx.createWebSocket(wssSource); - socket.onerror = function (e) { - triggerErrorEvent(elt, "htmx:wsError", {error:e, socket:socket}); - maybeCloseWebSocketSource(elt); - }; - - socket.onclose = function (e) { - if ([1006, 1012, 1013].indexOf(e.code) >= 0) { // Abnormal Closure/Service Restart/Try Again Later - var delay = getWebSocketReconnectDelay(retryCount); - setTimeout(function() { - ensureWebSocket(elt, wssSource, retryCount+1); // creates a websocket with a new timeout - }, delay); - } - }; - socket.onopen = function (e) { - retryCount = 0; - } - - getInternalData(elt).webSocket = socket; - socket.addEventListener('message', function (event) { - if (maybeCloseWebSocketSource(elt)) { - return; - } - - var response = event.data; - withExtensions(elt, function(extension){ - response = extension.transformResponse(response, null, elt); - }); - - var settleInfo = makeSettleInfo(elt); - var fragment = makeFragment(response); - var children = toArray(fragment.children); - for (var i = 0; i < children.length; i++) { - var child = children[i]; - oobSwap(getAttributeValue(child, "hx-swap-oob") || "true", child, settleInfo); - } - - settleImmediately(settleInfo.tasks); - }); - } - - function maybeCloseWebSocketSource(elt) { - if (!bodyContains(elt)) { - getInternalData(elt).webSocket.close(); - return true; - } - } - - function processWebSocketSend(elt) { - var webSocketSourceElt = getClosestMatch(elt, function (parent) { - return getInternalData(parent).webSocket != null; - }); - if (webSocketSourceElt) { - elt.addEventListener(getTriggerSpecs(elt)[0].trigger, function (evt) { - var webSocket = getInternalData(webSocketSourceElt).webSocket; - var headers = getHeaders(elt, webSocketSourceElt); - var results = getInputValues(elt, 'post'); - var errors = results.errors; - var rawParameters = results.values; - var expressionVars = getExpressionVars(elt); - var allParameters = mergeObjects(rawParameters, expressionVars); - var filteredParameters = filterValues(allParameters, elt); - filteredParameters['HEADERS'] = headers; - if (errors && errors.length > 0) { - triggerEvent(elt, 'htmx:validation:halted', errors); - return; - } - webSocket.send(JSON.stringify(filteredParameters)); - if(shouldCancel(evt, elt)){ - evt.preventDefault(); - } - }); - } else { - triggerErrorEvent(elt, "htmx:noWebSocketSourceError"); - } - } - - function getWebSocketReconnectDelay(retryCount) { - var delay = htmx.config.wsReconnectDelay; - if (typeof delay === 'function') { - // @ts-ignore - return delay(retryCount); - } - if (delay === 'full-jitter') { - var exp = Math.min(retryCount, 6); - var maxDelay = 1000 * Math.pow(2, exp); - return maxDelay * Math.random(); - } - logError('htmx.config.wsReconnectDelay must either be a function or the string "full-jitter"'); - } - - //==================================================================== - // Server Sent Events - //==================================================================== - - function processSSEInfo(elt, nodeData, info) { - var values = splitOnWhitespace(info); - for (var i = 0; i < values.length; i++) { - var value = values[i].split(/:(.+)/); - if (value[0] === "connect") { - processSSESource(elt, value[1]); - } - - if ((value[0] === "swap")) { - processSSESwap(elt, value[1]) - } - } - } - - function processSSESource(elt, sseSrc) { - var source = htmx.createEventSource(sseSrc); - source.onerror = function (e) { - triggerErrorEvent(elt, "htmx:sseError", {error:e, source:source}); - maybeCloseSSESource(elt); - }; - getInternalData(elt).sseEventSource = source; - } - - function processSSESwap(elt, sseEventName) { - var sseSourceElt = getClosestMatch(elt, hasEventSource); - if (sseSourceElt) { - var sseEventSource = getInternalData(sseSourceElt).sseEventSource; - var sseListener = function (event) { - if (maybeCloseSSESource(sseSourceElt)) { - return; - } - if (!bodyContains(elt)) { - sseEventSource.removeEventListener(sseEventName, sseListener); - return; - } - - /////////////////////////// - // TODO: merge this code with AJAX and WebSockets code in the future. - - var response = event.data; - withExtensions(elt, function(extension){ - response = extension.transformResponse(response, null, elt); - }); - - var swapSpec = getSwapSpecification(elt) - var target = getTarget(elt) - var settleInfo = makeSettleInfo(elt); - - selectAndSwap(swapSpec.swapStyle, target, elt, response, settleInfo) - settleImmediately(settleInfo.tasks) - triggerEvent(elt, "htmx:sseMessage", event) - }; - - getInternalData(elt).sseListener = sseListener; - sseEventSource.addEventListener(sseEventName, sseListener); - } else { - triggerErrorEvent(elt, "htmx:noSSESourceError"); - } - } - - function processSSETrigger(elt, handler, sseEventName) { - var sseSourceElt = getClosestMatch(elt, hasEventSource); - if (sseSourceElt) { - var sseEventSource = getInternalData(sseSourceElt).sseEventSource; - var sseListener = function () { - if (!maybeCloseSSESource(sseSourceElt)) { - if (bodyContains(elt)) { - handler(elt); - } else { - sseEventSource.removeEventListener(sseEventName, sseListener); - } - } - }; - getInternalData(elt).sseListener = sseListener; - sseEventSource.addEventListener(sseEventName, sseListener); - } else { - triggerErrorEvent(elt, "htmx:noSSESourceError"); - } - } - - function maybeCloseSSESource(elt) { - if (!bodyContains(elt)) { - getInternalData(elt).sseEventSource.close(); - return true; - } - } - - function hasEventSource(node) { - return getInternalData(node).sseEventSource != null; - } - - //==================================================================== - - function loadImmediately(elt, handler, nodeData, delay) { - var load = function(){ - if (!nodeData.loaded) { - nodeData.loaded = true; - handler(elt); - } - } - if (delay > 0) { - setTimeout(load, delay); - } else { - load(); - } - } - - function processVerbs(elt, nodeData, triggerSpecs) { - var explicitAction = false; - forEach(VERBS, function (verb) { - if (hasAttribute(elt,'hx-' + verb)) { - var path = getAttributeValue(elt, 'hx-' + verb); - explicitAction = true; - nodeData.path = path; - nodeData.verb = verb; - triggerSpecs.forEach(function(triggerSpec) { - addTriggerHandler(elt, triggerSpec, nodeData, function (elt, evt) { - if (closest(elt, htmx.config.disableSelector)) { - cleanUpElement(elt) - return - } - issueAjaxRequest(verb, path, elt, evt) - }) - }); - } - }); - return explicitAction; - } - - function addTriggerHandler(elt, triggerSpec, nodeData, handler) { - if (triggerSpec.sseEvent) { - processSSETrigger(elt, handler, triggerSpec.sseEvent); - } else if (triggerSpec.trigger === "revealed") { - initScrollHandler(); - addEventListener(elt, handler, nodeData, triggerSpec); - maybeReveal(elt); - } else if (triggerSpec.trigger === "intersect") { - var observerOptions = {}; - if (triggerSpec.root) { - observerOptions.root = querySelectorExt(elt, triggerSpec.root) - } - if (triggerSpec.threshold) { - observerOptions.threshold = parseFloat(triggerSpec.threshold); - } - var observer = new IntersectionObserver(function (entries) { - for (var i = 0; i < entries.length; i++) { - var entry = entries[i]; - if (entry.isIntersecting) { - triggerEvent(elt, "intersect"); - break; - } - } - }, observerOptions); - observer.observe(elt); - addEventListener(elt, handler, nodeData, triggerSpec); - } else if (triggerSpec.trigger === "load") { - if (!maybeFilterEvent(triggerSpec, elt, makeEvent("load", {elt: elt}))) { - loadImmediately(elt, handler, nodeData, triggerSpec.delay); - } - } else if (triggerSpec.pollInterval > 0) { - nodeData.polling = true; - processPolling(elt, handler, triggerSpec); - } else { - addEventListener(elt, handler, nodeData, triggerSpec); - } - } - - function evalScript(script) { - if (!script.htmxExecuted && htmx.config.allowScriptTags && - (script.type === "text/javascript" || script.type === "module" || script.type === "") ) { - var newScript = getDocument().createElement("script"); - forEach(script.attributes, function (attr) { - newScript.setAttribute(attr.name, attr.value); - }); - newScript.textContent = script.textContent; - newScript.async = false; - if (htmx.config.inlineScriptNonce) { - newScript.nonce = htmx.config.inlineScriptNonce; - } - var parent = script.parentElement; - - try { - parent.insertBefore(newScript, script); - } catch (e) { - logError(e); - } finally { - // remove old script element, but only if it is still in DOM - if (script.parentElement) { - script.parentElement.removeChild(script); - } - } - } - } - - function processScripts(elt) { - if (matches(elt, "script")) { - evalScript(elt); - } - forEach(findAll(elt, "script"), function (script) { - evalScript(script); - }); - } - - function shouldProcessHxOn(elt) { - var attributes = elt.attributes - for (var j = 0; j < attributes.length; j++) { - var attrName = attributes[j].name - if (startsWith(attrName, "hx-on:") || startsWith(attrName, "data-hx-on:") || - startsWith(attrName, "hx-on-") || startsWith(attrName, "data-hx-on-")) { - return true - } - } - return false - } - - function findHxOnWildcardElements(elt) { - var node = null - var elements = [] - - if (shouldProcessHxOn(elt)) { - elements.push(elt) - } - - if (document.evaluate) { - var iter = document.evaluate('.//*[@*[ starts-with(name(), "hx-on:") or starts-with(name(), "data-hx-on:") or' + - ' starts-with(name(), "hx-on-") or starts-with(name(), "data-hx-on-") ]]', elt) - while (node = iter.iterateNext()) elements.push(node) - } else { - var allElements = elt.getElementsByTagName("*") - for (var i = 0; i < allElements.length; i++) { - if (shouldProcessHxOn(allElements[i])) { - elements.push(allElements[i]) - } - } - } - - return elements - } - - function findElementsToProcess(elt) { - if (elt.querySelectorAll) { - var boostedSelector = ", [hx-boost] a, [data-hx-boost] a, a[hx-boost], a[data-hx-boost]"; - var results = elt.querySelectorAll(VERB_SELECTOR + boostedSelector + ", form, [type='submit'], [hx-sse], [data-hx-sse], [hx-ws]," + - " [data-hx-ws], [hx-ext], [data-hx-ext], [hx-trigger], [data-hx-trigger], [hx-on], [data-hx-on]"); - return results; - } else { - return []; - } - } - - // Handle submit buttons/inputs that have the form attribute set - // see https://developer.mozilla.org/docs/Web/HTML/Element/button - function maybeSetLastButtonClicked(evt) { - var elt = closest(evt.target, "button, input[type='submit']"); - var internalData = getRelatedFormData(evt) - if (internalData) { - internalData.lastButtonClicked = elt; - } - }; - function maybeUnsetLastButtonClicked(evt){ - var internalData = getRelatedFormData(evt) - if (internalData) { - internalData.lastButtonClicked = null; - } - } - function getRelatedFormData(evt) { - var elt = closest(evt.target, "button, input[type='submit']"); - if (!elt) { - return; - } - var form = resolveTarget('#' + getRawAttribute(elt, 'form')) || closest(elt, 'form'); - if (!form) { - return; - } - return getInternalData(form); - } - function initButtonTracking(elt) { - // need to handle both click and focus in: - // focusin - in case someone tabs in to a button and hits the space bar - // click - on OSX buttons do not focus on click see https://bugs.webkit.org/show_bug.cgi?id=13724 - elt.addEventListener('click', maybeSetLastButtonClicked) - elt.addEventListener('focusin', maybeSetLastButtonClicked) - elt.addEventListener('focusout', maybeUnsetLastButtonClicked) - } - - function countCurlies(line) { - var tokens = tokenizeString(line); - var netCurlies = 0; - for (var i = 0; i < tokens.length; i++) { - const token = tokens[i]; - if (token === "{") { - netCurlies++; - } else if (token === "}") { - netCurlies--; - } - } - return netCurlies; - } - - function addHxOnEventHandler(elt, eventName, code) { - var nodeData = getInternalData(elt); - if (!Array.isArray(nodeData.onHandlers)) { - nodeData.onHandlers = []; - } - var func; - var listener = function (e) { - return maybeEval(elt, function() { - if (!func) { - func = new Function("event", code); - } - func.call(elt, e); - }); - }; - elt.addEventListener(eventName, listener); - nodeData.onHandlers.push({event:eventName, listener:listener}); - } - - function processHxOn(elt) { - var hxOnValue = getAttributeValue(elt, 'hx-on'); - if (hxOnValue) { - var handlers = {} - var lines = hxOnValue.split("\n"); - var currentEvent = null; - var curlyCount = 0; - while (lines.length > 0) { - var line = lines.shift(); - var match = line.match(/^\s*([a-zA-Z:\-\.]+:)(.*)/); - if (curlyCount === 0 && match) { - line.split(":") - currentEvent = match[1].slice(0, -1); // strip last colon - handlers[currentEvent] = match[2]; - } else { - handlers[currentEvent] += line; - } - curlyCount += countCurlies(line); - } - - for (var eventName in handlers) { - addHxOnEventHandler(elt, eventName, handlers[eventName]); - } - } - } - - function processHxOnWildcard(elt) { - // wipe any previous on handlers so that this function takes precedence - deInitOnHandlers(elt) - - for (var i = 0; i < elt.attributes.length; i++) { - var name = elt.attributes[i].name - var value = elt.attributes[i].value - if (startsWith(name, "hx-on") || startsWith(name, "data-hx-on")) { - var afterOnPosition = name.indexOf("-on") + 3; - var nextChar = name.slice(afterOnPosition, afterOnPosition + 1); - if (nextChar === "-" || nextChar === ":") { - var eventName = name.slice(afterOnPosition + 1); - // if the eventName starts with a colon or dash, prepend "htmx" for shorthand support - if (startsWith(eventName, ":")) { - eventName = "htmx" + eventName - } else if (startsWith(eventName, "-")) { - eventName = "htmx:" + eventName.slice(1); - } else if (startsWith(eventName, "htmx-")) { - eventName = "htmx:" + eventName.slice(5); - } - - addHxOnEventHandler(elt, eventName, value) - } - } - } - } - - function initNode(elt) { - if (closest(elt, htmx.config.disableSelector)) { - cleanUpElement(elt) - return; - } - var nodeData = getInternalData(elt); - if (nodeData.initHash !== attributeHash(elt)) { - // clean up any previously processed info - deInitNode(elt); - - nodeData.initHash = attributeHash(elt); - - processHxOn(elt); - - triggerEvent(elt, "htmx:beforeProcessNode") - - if (elt.value) { - nodeData.lastValue = elt.value; - } - - var triggerSpecs = getTriggerSpecs(elt); - var hasExplicitHttpAction = processVerbs(elt, nodeData, triggerSpecs); - - if (!hasExplicitHttpAction) { - if (getClosestAttributeValue(elt, "hx-boost") === "true") { - boostElement(elt, nodeData, triggerSpecs); - } else if (hasAttribute(elt, 'hx-trigger')) { - triggerSpecs.forEach(function (triggerSpec) { - // For "naked" triggers, don't do anything at all - addTriggerHandler(elt, triggerSpec, nodeData, function () { - }) - }) - } - } - - // Handle submit buttons/inputs that have the form attribute set - // see https://developer.mozilla.org/docs/Web/HTML/Element/button - if (elt.tagName === "FORM" || (getRawAttribute(elt, "type") === "submit" && hasAttribute(elt, "form"))) { - initButtonTracking(elt) - } - - var sseInfo = getAttributeValue(elt, 'hx-sse'); - if (sseInfo) { - processSSEInfo(elt, nodeData, sseInfo); - } - - var wsInfo = getAttributeValue(elt, 'hx-ws'); - if (wsInfo) { - processWebSocketInfo(elt, nodeData, wsInfo); - } - triggerEvent(elt, "htmx:afterProcessNode"); - } - } - - function processNode(elt) { - elt = resolveTarget(elt); - if (closest(elt, htmx.config.disableSelector)) { - cleanUpElement(elt) - return; - } - initNode(elt); - forEach(findElementsToProcess(elt), function(child) { initNode(child) }); - // Because it happens second, the new way of adding onHandlers superseeds the old one - // i.e. if there are any hx-on:eventName attributes, the hx-on attribute will be ignored - forEach(findHxOnWildcardElements(elt), processHxOnWildcard); - } - - //==================================================================== - // Event/Log Support - //==================================================================== - - function kebabEventName(str) { - return str.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase(); - } - - function makeEvent(eventName, detail) { - var evt; - if (window.CustomEvent && typeof window.CustomEvent === 'function') { - evt = new CustomEvent(eventName, {bubbles: true, cancelable: true, detail: detail}); - } else { - evt = getDocument().createEvent('CustomEvent'); - evt.initCustomEvent(eventName, true, true, detail); - } - return evt; - } - - function triggerErrorEvent(elt, eventName, detail) { - triggerEvent(elt, eventName, mergeObjects({error:eventName}, detail)); - } - - function ignoreEventForLogging(eventName) { - return eventName === "htmx:afterProcessNode" - } - - /** - * `withExtensions` locates all active extensions for a provided element, then - * executes the provided function using each of the active extensions. It should - * be called internally at every extendable execution point in htmx. - * - * @param {HTMLElement} elt - * @param {(extension:import("./htmx").HtmxExtension) => void} toDo - * @returns void - */ - function withExtensions(elt, toDo) { - forEach(getExtensions(elt), function(extension){ - try { - toDo(extension); - } catch (e) { - logError(e); - } - }); - } - - function logError(msg) { - if(console.error) { - console.error(msg); - } else if (console.log) { - console.log("ERROR: ", msg); - } - } - - function triggerEvent(elt, eventName, detail) { - elt = resolveTarget(elt); - if (detail == null) { - detail = {}; - } - detail["elt"] = elt; - var event = makeEvent(eventName, detail); - if (htmx.logger && !ignoreEventForLogging(eventName)) { - htmx.logger(elt, eventName, detail); - } - if (detail.error) { - logError(detail.error); - triggerEvent(elt, "htmx:error", {errorInfo:detail}) - } - var eventResult = elt.dispatchEvent(event); - var kebabName = kebabEventName(eventName); - if (eventResult && kebabName !== eventName) { - var kebabedEvent = makeEvent(kebabName, event.detail); - eventResult = eventResult && elt.dispatchEvent(kebabedEvent) - } - withExtensions(elt, function (extension) { - eventResult = eventResult && (extension.onEvent(eventName, event) !== false && !event.defaultPrevented) - }); - return eventResult; - } - - //==================================================================== - // History Support - //==================================================================== - var currentPathForHistory = location.pathname+location.search; - - function getHistoryElement() { - var historyElt = getDocument().querySelector('[hx-history-elt],[data-hx-history-elt]'); - return historyElt || getDocument().body; - } - - function saveToHistoryCache(url, content, title, scroll) { - if (!canAccessLocalStorage()) { - return; - } - - if (htmx.config.historyCacheSize <= 0) { - // make sure that an eventually already existing cache is purged - localStorage.removeItem("htmx-history-cache"); - return; - } - - url = normalizePath(url); - - var historyCache = parseJSON(localStorage.getItem("htmx-history-cache")) || []; - for (var i = 0; i < historyCache.length; i++) { - if (historyCache[i].url === url) { - historyCache.splice(i, 1); - break; - } - } - var newHistoryItem = {url:url, content: content, title:title, scroll:scroll}; - triggerEvent(getDocument().body, "htmx:historyItemCreated", {item:newHistoryItem, cache: historyCache}) - historyCache.push(newHistoryItem) - while (historyCache.length > htmx.config.historyCacheSize) { - historyCache.shift(); - } - while(historyCache.length > 0){ - try { - localStorage.setItem("htmx-history-cache", JSON.stringify(historyCache)); - break; - } catch (e) { - triggerErrorEvent(getDocument().body, "htmx:historyCacheError", {cause:e, cache: historyCache}) - historyCache.shift(); // shrink the cache and retry - } - } - } - - function getCachedHistory(url) { - if (!canAccessLocalStorage()) { - return null; - } - - url = normalizePath(url); - - var historyCache = parseJSON(localStorage.getItem("htmx-history-cache")) || []; - for (var i = 0; i < historyCache.length; i++) { - if (historyCache[i].url === url) { - return historyCache[i]; - } - } - return null; - } - - function cleanInnerHtmlForHistory(elt) { - var className = htmx.config.requestClass; - var clone = elt.cloneNode(true); - forEach(findAll(clone, "." + className), function(child){ - removeClassFromElement(child, className); - }); - return clone.innerHTML; - } - - function saveCurrentPageToHistory() { - var elt = getHistoryElement(); - var path = currentPathForHistory || location.pathname+location.search; - - // Allow history snapshot feature to be disabled where hx-history="false" - // is present *anywhere* in the current document we're about to save, - // so we can prevent privileged data entering the cache. - // The page will still be reachable as a history entry, but htmx will fetch it - // live from the server onpopstate rather than look in the localStorage cache - var disableHistoryCache - try { - disableHistoryCache = getDocument().querySelector('[hx-history="false" i],[data-hx-history="false" i]') - } catch (e) { - // IE11: insensitive modifier not supported so fallback to case sensitive selector - disableHistoryCache = getDocument().querySelector('[hx-history="false"],[data-hx-history="false"]') - } - if (!disableHistoryCache) { - triggerEvent(getDocument().body, "htmx:beforeHistorySave", {path: path, historyElt: elt}); - saveToHistoryCache(path, cleanInnerHtmlForHistory(elt), getDocument().title, window.scrollY); - } - - if (htmx.config.historyEnabled) history.replaceState({htmx: true}, getDocument().title, window.location.href); - } - - function pushUrlIntoHistory(path) { - // remove the cache buster parameter, if any - if (htmx.config.getCacheBusterParam) { - path = path.replace(/org\.htmx\.cache-buster=[^&]*&?/, '') - if (endsWith(path, '&') || endsWith(path, "?")) { - path = path.slice(0, -1); - } - } - if(htmx.config.historyEnabled) { - history.pushState({htmx:true}, "", path); - } - currentPathForHistory = path; - } - - function replaceUrlInHistory(path) { - if(htmx.config.historyEnabled) history.replaceState({htmx:true}, "", path); - currentPathForHistory = path; - } - - function settleImmediately(tasks) { - forEach(tasks, function (task) { - task.call(); - }); - } - - function loadHistoryFromServer(path) { - var request = new XMLHttpRequest(); - var details = {path: path, xhr:request}; - triggerEvent(getDocument().body, "htmx:historyCacheMiss", details); - request.open('GET', path, true); - request.setRequestHeader("HX-Request", "true"); - request.setRequestHeader("HX-History-Restore-Request", "true"); - request.setRequestHeader("HX-Current-URL", getDocument().location.href); - request.onload = function () { - if (this.status >= 200 && this.status < 400) { - triggerEvent(getDocument().body, "htmx:historyCacheMissLoad", details); - var fragment = makeFragment(this.response); - // @ts-ignore - fragment = fragment.querySelector('[hx-history-elt],[data-hx-history-elt]') || fragment; - var historyElement = getHistoryElement(); - var settleInfo = makeSettleInfo(historyElement); - var title = findTitle(this.response); - if (title) { - var titleElt = find("title"); - if (titleElt) { - titleElt.innerHTML = title; - } else { - window.document.title = title; - } - } - // @ts-ignore - swapInnerHTML(historyElement, fragment, settleInfo) - settleImmediately(settleInfo.tasks); - currentPathForHistory = path; - triggerEvent(getDocument().body, "htmx:historyRestore", {path: path, cacheMiss:true, serverResponse:this.response}); - } else { - triggerErrorEvent(getDocument().body, "htmx:historyCacheMissLoadError", details); - } - }; - request.send(); - } - - function restoreHistory(path) { - saveCurrentPageToHistory(); - path = path || location.pathname+location.search; - var cached = getCachedHistory(path); - if (cached) { - var fragment = makeFragment(cached.content); - var historyElement = getHistoryElement(); - var settleInfo = makeSettleInfo(historyElement); - swapInnerHTML(historyElement, fragment, settleInfo) - settleImmediately(settleInfo.tasks); - document.title = cached.title; - setTimeout(function () { - window.scrollTo(0, cached.scroll); - }, 0); // next 'tick', so browser has time to render layout - currentPathForHistory = path; - triggerEvent(getDocument().body, "htmx:historyRestore", {path:path, item:cached}); - } else { - if (htmx.config.refreshOnHistoryMiss) { - - // @ts-ignore: optional parameter in reload() function throws error - window.location.reload(true); - } else { - loadHistoryFromServer(path); - } - } - } - - function addRequestIndicatorClasses(elt) { - var indicators = findAttributeTargets(elt, 'hx-indicator'); - if (indicators == null) { - indicators = [elt]; - } - forEach(indicators, function (ic) { - var internalData = getInternalData(ic); - internalData.requestCount = (internalData.requestCount || 0) + 1; - ic.classList["add"].call(ic.classList, htmx.config.requestClass); - }); - return indicators; - } - - function disableElements(elt) { - var disabledElts = findAttributeTargets(elt, 'hx-disabled-elt'); - if (disabledElts == null) { - disabledElts = []; - } - forEach(disabledElts, function (disabledElement) { - var internalData = getInternalData(disabledElement); - internalData.requestCount = (internalData.requestCount || 0) + 1; - disabledElement.setAttribute("disabled", ""); - }); - return disabledElts; - } - - function removeRequestIndicators(indicators, disabled) { - forEach(indicators, function (ic) { - var internalData = getInternalData(ic); - internalData.requestCount = (internalData.requestCount || 0) - 1; - if (internalData.requestCount === 0) { - ic.classList["remove"].call(ic.classList, htmx.config.requestClass); - } - }); - forEach(disabled, function (disabledElement) { - var internalData = getInternalData(disabledElement); - internalData.requestCount = (internalData.requestCount || 0) - 1; - if (internalData.requestCount === 0) { - disabledElement.removeAttribute('disabled'); - } - }); - } - - //==================================================================== - // Input Value Processing - //==================================================================== - - function haveSeenNode(processed, elt) { - for (var i = 0; i < processed.length; i++) { - var node = processed[i]; - if (node.isSameNode(elt)) { - return true; - } - } - return false; - } - - function shouldInclude(elt) { - if(elt.name === "" || elt.name == null || elt.disabled || closest(elt, "fieldset[disabled]")) { - return false; - } - // ignore "submitter" types (see jQuery src/serialize.js) - if (elt.type === "button" || elt.type === "submit" || elt.tagName === "image" || elt.tagName === "reset" || elt.tagName === "file" ) { - return false; - } - if (elt.type === "checkbox" || elt.type === "radio" ) { - return elt.checked; - } - return true; - } - - function addValueToValues(name, value, values) { - // This is a little ugly because both the current value of the named value in the form - // and the new value could be arrays, so we have to handle all four cases :/ - if (name != null && value != null) { - var current = values[name]; - if (current === undefined) { - values[name] = value; - } else if (Array.isArray(current)) { - if (Array.isArray(value)) { - values[name] = current.concat(value); - } else { - current.push(value); - } - } else { - if (Array.isArray(value)) { - values[name] = [current].concat(value); - } else { - values[name] = [current, value]; - } - } - } - } - - function processInputValue(processed, values, errors, elt, validate) { - if (elt == null || haveSeenNode(processed, elt)) { - return; - } else { - processed.push(elt); - } - if (shouldInclude(elt)) { - var name = getRawAttribute(elt,"name"); - var value = elt.value; - if (elt.multiple && elt.tagName === "SELECT") { - value = toArray(elt.querySelectorAll("option:checked")).map(function (e) { return e.value }); - } - // include file inputs - if (elt.files) { - value = toArray(elt.files); - } - addValueToValues(name, value, values); - if (validate) { - validateElement(elt, errors); - } - } - if (matches(elt, 'form')) { - var inputs = elt.elements; - forEach(inputs, function(input) { - processInputValue(processed, values, errors, input, validate); - }); - } - } - - function validateElement(element, errors) { - if (element.willValidate) { - triggerEvent(element, "htmx:validation:validate") - if (!element.checkValidity()) { - errors.push({elt: element, message:element.validationMessage, validity:element.validity}); - triggerEvent(element, "htmx:validation:failed", {message:element.validationMessage, validity:element.validity}) - } - } - } - - /** - * @param {HTMLElement} elt - * @param {string} verb - */ - function getInputValues(elt, verb) { - var processed = []; - var values = {}; - var formValues = {}; - var errors = []; - var internalData = getInternalData(elt); - if (internalData.lastButtonClicked && !bodyContains(internalData.lastButtonClicked)) { - internalData.lastButtonClicked = null - } - - // only validate when form is directly submitted and novalidate or formnovalidate are not set - // or if the element has an explicit hx-validate="true" on it - var validate = (matches(elt, 'form') && elt.noValidate !== true) || getAttributeValue(elt, "hx-validate") === "true"; - if (internalData.lastButtonClicked) { - validate = validate && internalData.lastButtonClicked.formNoValidate !== true; - } - - // for a non-GET include the closest form - if (verb !== 'get') { - processInputValue(processed, formValues, errors, closest(elt, 'form'), validate); - } - - // include the element itself - processInputValue(processed, values, errors, elt, validate); - - // if a button or submit was clicked last, include its value - if (internalData.lastButtonClicked || elt.tagName === "BUTTON" || - (elt.tagName === "INPUT" && getRawAttribute(elt, "type") === "submit")) { - var button = internalData.lastButtonClicked || elt - var name = getRawAttribute(button, "name") - addValueToValues(name, button.value, formValues) - } - - // include any explicit includes - var includes = findAttributeTargets(elt, "hx-include"); - forEach(includes, function(node) { - processInputValue(processed, values, errors, node, validate); - // if a non-form is included, include any input values within it - if (!matches(node, 'form')) { - forEach(node.querySelectorAll(INPUT_SELECTOR), function (descendant) { - processInputValue(processed, values, errors, descendant, validate); - }) - } - }); - - // form values take precedence, overriding the regular values - values = mergeObjects(values, formValues); - - return {errors:errors, values:values}; - } - - function appendParam(returnStr, name, realValue) { - if (returnStr !== "") { - returnStr += "&"; - } - if (String(realValue) === "[object Object]") { - realValue = JSON.stringify(realValue); - } - var s = encodeURIComponent(realValue); - returnStr += encodeURIComponent(name) + "=" + s; - return returnStr; - } - - function urlEncode(values) { - var returnStr = ""; - for (var name in values) { - if (values.hasOwnProperty(name)) { - var value = values[name]; - if (Array.isArray(value)) { - forEach(value, function(v) { - returnStr = appendParam(returnStr, name, v); - }); - } else { - returnStr = appendParam(returnStr, name, value); - } - } - } - return returnStr; - } - - function makeFormData(values) { - var formData = new FormData(); - for (var name in values) { - if (values.hasOwnProperty(name)) { - var value = values[name]; - if (Array.isArray(value)) { - forEach(value, function(v) { - formData.append(name, v); - }); - } else { - formData.append(name, value); - } - } - } - return formData; - } - - //==================================================================== - // Ajax - //==================================================================== - - /** - * @param {HTMLElement} elt - * @param {HTMLElement} target - * @param {string} prompt - * @returns {Object} // TODO: Define/Improve HtmxHeaderSpecification - */ - function getHeaders(elt, target, prompt) { - var headers = { - "HX-Request" : "true", - "HX-Trigger" : getRawAttribute(elt, "id"), - "HX-Trigger-Name" : getRawAttribute(elt, "name"), - "HX-Target" : getAttributeValue(target, "id"), - "HX-Current-URL" : getDocument().location.href, - } - getValuesForElement(elt, "hx-headers", false, headers) - if (prompt !== undefined) { - headers["HX-Prompt"] = prompt; - } - if (getInternalData(elt).boosted) { - headers["HX-Boosted"] = "true"; - } - return headers; - } - - /** - * filterValues takes an object containing form input values - * and returns a new object that only contains keys that are - * specified by the closest "hx-params" attribute - * @param {Object} inputValues - * @param {HTMLElement} elt - * @returns {Object} - */ - function filterValues(inputValues, elt) { - var paramsValue = getClosestAttributeValue(elt, "hx-params"); - if (paramsValue) { - if (paramsValue === "none") { - return {}; - } else if (paramsValue === "*") { - return inputValues; - } else if(paramsValue.indexOf("not ") === 0) { - forEach(paramsValue.substr(4).split(","), function (name) { - name = name.trim(); - delete inputValues[name]; - }); - return inputValues; - } else { - var newValues = {} - forEach(paramsValue.split(","), function (name) { - name = name.trim(); - newValues[name] = inputValues[name]; - }); - return newValues; - } - } else { - return inputValues; - } - } - - function isAnchorLink(elt) { - return getRawAttribute(elt, 'href') && getRawAttribute(elt, 'href').indexOf("#") >=0 - } - - /** - * - * @param {HTMLElement} elt - * @param {string} swapInfoOverride - * @returns {import("./htmx").HtmxSwapSpecification} - */ - function getSwapSpecification(elt, swapInfoOverride) { - var swapInfo = swapInfoOverride ? swapInfoOverride : getClosestAttributeValue(elt, "hx-swap"); - var swapSpec = { - "swapStyle" : getInternalData(elt).boosted ? 'innerHTML' : htmx.config.defaultSwapStyle, - "swapDelay" : htmx.config.defaultSwapDelay, - "settleDelay" : htmx.config.defaultSettleDelay - } - if (htmx.config.scrollIntoViewOnBoost && getInternalData(elt).boosted && !isAnchorLink(elt)) { - swapSpec["show"] = "top" - } - if (swapInfo) { - var split = splitOnWhitespace(swapInfo); - if (split.length > 0) { - for (var i = 0; i < split.length; i++) { - var value = split[i]; - if (value.indexOf("swap:") === 0) { - swapSpec["swapDelay"] = parseInterval(value.substr(5)); - } else if (value.indexOf("settle:") === 0) { - swapSpec["settleDelay"] = parseInterval(value.substr(7)); - } else if (value.indexOf("transition:") === 0) { - swapSpec["transition"] = value.substr(11) === "true"; - } else if (value.indexOf("ignoreTitle:") === 0) { - swapSpec["ignoreTitle"] = value.substr(12) === "true"; - } else if (value.indexOf("scroll:") === 0) { - var scrollSpec = value.substr(7); - var splitSpec = scrollSpec.split(":"); - var scrollVal = splitSpec.pop(); - var selectorVal = splitSpec.length > 0 ? splitSpec.join(":") : null; - swapSpec["scroll"] = scrollVal; - swapSpec["scrollTarget"] = selectorVal; - } else if (value.indexOf("show:") === 0) { - var showSpec = value.substr(5); - var splitSpec = showSpec.split(":"); - var showVal = splitSpec.pop(); - var selectorVal = splitSpec.length > 0 ? splitSpec.join(":") : null; - swapSpec["show"] = showVal; - swapSpec["showTarget"] = selectorVal; - } else if (value.indexOf("focus-scroll:") === 0) { - var focusScrollVal = value.substr("focus-scroll:".length); - swapSpec["focusScroll"] = focusScrollVal == "true"; - } else if (i == 0) { - swapSpec["swapStyle"] = value; - } else { - logError('Unknown modifier in hx-swap: ' + value); - } - } - } - } - return swapSpec; - } - - function usesFormData(elt) { - return getClosestAttributeValue(elt, "hx-encoding") === "multipart/form-data" || - (matches(elt, "form") && getRawAttribute(elt, 'enctype') === "multipart/form-data"); - } - - function encodeParamsForBody(xhr, elt, filteredParameters) { - var encodedParameters = null; - withExtensions(elt, function (extension) { - if (encodedParameters == null) { - encodedParameters = extension.encodeParameters(xhr, filteredParameters, elt); - } - }); - if (encodedParameters != null) { - return encodedParameters; - } else { - if (usesFormData(elt)) { - return makeFormData(filteredParameters); - } else { - return urlEncode(filteredParameters); - } - } - } - - /** - * - * @param {Element} target - * @returns {import("./htmx").HtmxSettleInfo} - */ - function makeSettleInfo(target) { - return {tasks: [], elts: [target]}; - } - - function updateScrollState(content, swapSpec) { - var first = content[0]; - var last = content[content.length - 1]; - if (swapSpec.scroll) { - var target = null; - if (swapSpec.scrollTarget) { - target = querySelectorExt(first, swapSpec.scrollTarget); - } - if (swapSpec.scroll === "top" && (first || target)) { - target = target || first; - target.scrollTop = 0; - } - if (swapSpec.scroll === "bottom" && (last || target)) { - target = target || last; - target.scrollTop = target.scrollHeight; - } - } - if (swapSpec.show) { - var target = null; - if (swapSpec.showTarget) { - var targetStr = swapSpec.showTarget; - if (swapSpec.showTarget === "window") { - targetStr = "body"; - } - target = querySelectorExt(first, targetStr); - } - if (swapSpec.show === "top" && (first || target)) { - target = target || first; - target.scrollIntoView({block:'start', behavior: htmx.config.scrollBehavior}); - } - if (swapSpec.show === "bottom" && (last || target)) { - target = target || last; - target.scrollIntoView({block:'end', behavior: htmx.config.scrollBehavior}); - } - } - } - - /** - * @param {HTMLElement} elt - * @param {string} attr - * @param {boolean=} evalAsDefault - * @param {Object=} values - * @returns {Object} - */ - function getValuesForElement(elt, attr, evalAsDefault, values) { - if (values == null) { - values = {}; - } - if (elt == null) { - return values; - } - var attributeValue = getAttributeValue(elt, attr); - if (attributeValue) { - var str = attributeValue.trim(); - var evaluateValue = evalAsDefault; - if (str === "unset") { - return null; - } - if (str.indexOf("javascript:") === 0) { - str = str.substr(11); - evaluateValue = true; - } else if (str.indexOf("js:") === 0) { - str = str.substr(3); - evaluateValue = true; - } - if (str.indexOf('{') !== 0) { - str = "{" + str + "}"; - } - var varsValues; - if (evaluateValue) { - varsValues = maybeEval(elt,function () {return Function("return (" + str + ")")();}, {}); - } else { - varsValues = parseJSON(str); - } - for (var key in varsValues) { - if (varsValues.hasOwnProperty(key)) { - if (values[key] == null) { - values[key] = varsValues[key]; - } - } - } - } - return getValuesForElement(parentElt(elt), attr, evalAsDefault, values); - } - - function maybeEval(elt, toEval, defaultVal) { - if (htmx.config.allowEval) { - return toEval(); - } else { - triggerErrorEvent(elt, 'htmx:evalDisallowedError'); - return defaultVal; - } - } - - /** - * @param {HTMLElement} elt - * @param {*} expressionVars - * @returns - */ - function getHXVarsForElement(elt, expressionVars) { - return getValuesForElement(elt, "hx-vars", true, expressionVars); - } - - /** - * @param {HTMLElement} elt - * @param {*} expressionVars - * @returns - */ - function getHXValsForElement(elt, expressionVars) { - return getValuesForElement(elt, "hx-vals", false, expressionVars); - } - - /** - * @param {HTMLElement} elt - * @returns {Object} - */ - function getExpressionVars(elt) { - return mergeObjects(getHXVarsForElement(elt), getHXValsForElement(elt)); - } - - function safelySetHeaderValue(xhr, header, headerValue) { - if (headerValue !== null) { - try { - xhr.setRequestHeader(header, headerValue); - } catch (e) { - // On an exception, try to set the header URI encoded instead - xhr.setRequestHeader(header, encodeURIComponent(headerValue)); - xhr.setRequestHeader(header + "-URI-AutoEncoded", "true"); - } - } - } - - function getPathFromResponse(xhr) { - // NB: IE11 does not support this stuff - if (xhr.responseURL && typeof(URL) !== "undefined") { - try { - var url = new URL(xhr.responseURL); - return url.pathname + url.search; - } catch (e) { - triggerErrorEvent(getDocument().body, "htmx:badResponseUrl", {url: xhr.responseURL}); - } - } - } - - function hasHeader(xhr, regexp) { - return regexp.test(xhr.getAllResponseHeaders()) - } - - function ajaxHelper(verb, path, context) { - verb = verb.toLowerCase(); - if (context) { - if (context instanceof Element || isType(context, 'String')) { - return issueAjaxRequest(verb, path, null, null, { - targetOverride: resolveTarget(context), - returnPromise: true - }); - } else { - return issueAjaxRequest(verb, path, resolveTarget(context.source), context.event, - { - handler : context.handler, - headers : context.headers, - values : context.values, - targetOverride: resolveTarget(context.target), - swapOverride: context.swap, - select: context.select, - returnPromise: true - }); - } - } else { - return issueAjaxRequest(verb, path, null, null, { - returnPromise: true - }); - } - } - - function hierarchyForElt(elt) { - var arr = []; - while (elt) { - arr.push(elt); - elt = elt.parentElement; - } - return arr; - } - - function verifyPath(elt, path, requestConfig) { - var sameHost - var url - if (typeof URL === "function") { - url = new URL(path, document.location.href); - var origin = document.location.origin; - sameHost = origin === url.origin; - } else { - // IE11 doesn't support URL - url = path - sameHost = startsWith(path, document.location.origin) - } - - if (htmx.config.selfRequestsOnly) { - if (!sameHost) { - return false; - } - } - return triggerEvent(elt, "htmx:validateUrl", mergeObjects({url: url, sameHost: sameHost}, requestConfig)); - } - - function issueAjaxRequest(verb, path, elt, event, etc, confirmed) { - var resolve = null; - var reject = null; - etc = etc != null ? etc : {}; - if(etc.returnPromise && typeof Promise !== "undefined"){ - var promise = new Promise(function (_resolve, _reject) { - resolve = _resolve; - reject = _reject; - }); - } - if(elt == null) { - elt = getDocument().body; - } - var responseHandler = etc.handler || handleAjaxResponse; - var select = etc.select || null; - - if (!bodyContains(elt)) { - // do not issue requests for elements removed from the DOM - maybeCall(resolve); - return promise; - } - var target = etc.targetOverride || getTarget(elt); - if (target == null || target == DUMMY_ELT) { - triggerErrorEvent(elt, 'htmx:targetError', {target: getAttributeValue(elt, "hx-target")}); - maybeCall(reject); - return promise; - } - - var eltData = getInternalData(elt); - var submitter = eltData.lastButtonClicked; - - if (submitter) { - var buttonPath = getRawAttribute(submitter, "formaction"); - if (buttonPath != null) { - path = buttonPath; - } - - var buttonVerb = getRawAttribute(submitter, "formmethod") - if (buttonVerb != null) { - // ignore buttons with formmethod="dialog" - if (buttonVerb.toLowerCase() !== "dialog") { - verb = buttonVerb; - } - } - } - - var confirmQuestion = getClosestAttributeValue(elt, "hx-confirm"); - // allow event-based confirmation w/ a callback - if (confirmed === undefined) { - var issueRequest = function(skipConfirmation) { - return issueAjaxRequest(verb, path, elt, event, etc, !!skipConfirmation); - } - var confirmDetails = {target: target, elt: elt, path: path, verb: verb, triggeringEvent: event, etc: etc, issueRequest: issueRequest, question: confirmQuestion}; - if (triggerEvent(elt, 'htmx:confirm', confirmDetails) === false) { - maybeCall(resolve); - return promise; - } - } - - var syncElt = elt; - var syncStrategy = getClosestAttributeValue(elt, "hx-sync"); - var queueStrategy = null; - var abortable = false; - if (syncStrategy) { - var syncStrings = syncStrategy.split(":"); - var selector = syncStrings[0].trim(); - if (selector === "this") { - syncElt = findThisElement(elt, 'hx-sync'); - } else { - syncElt = querySelectorExt(elt, selector); - } - // default to the drop strategy - syncStrategy = (syncStrings[1] || 'drop').trim(); - eltData = getInternalData(syncElt); - if (syncStrategy === "drop" && eltData.xhr && eltData.abortable !== true) { - maybeCall(resolve); - return promise; - } else if (syncStrategy === "abort") { - if (eltData.xhr) { - maybeCall(resolve); - return promise; - } else { - abortable = true; - } - } else if (syncStrategy === "replace") { - triggerEvent(syncElt, 'htmx:abort'); // abort the current request and continue - } else if (syncStrategy.indexOf("queue") === 0) { - var queueStrArray = syncStrategy.split(" "); - queueStrategy = (queueStrArray[1] || "last").trim(); - } - } - - if (eltData.xhr) { - if (eltData.abortable) { - triggerEvent(syncElt, 'htmx:abort'); // abort the current request and continue - } else { - if(queueStrategy == null){ - if (event) { - var eventData = getInternalData(event); - if (eventData && eventData.triggerSpec && eventData.triggerSpec.queue) { - queueStrategy = eventData.triggerSpec.queue; - } - } - if (queueStrategy == null) { - queueStrategy = "last"; - } - } - if (eltData.queuedRequests == null) { - eltData.queuedRequests = []; - } - if (queueStrategy === "first" && eltData.queuedRequests.length === 0) { - eltData.queuedRequests.push(function () { - issueAjaxRequest(verb, path, elt, event, etc) - }); - } else if (queueStrategy === "all") { - eltData.queuedRequests.push(function () { - issueAjaxRequest(verb, path, elt, event, etc) - }); - } else if (queueStrategy === "last") { - eltData.queuedRequests = []; // dump existing queue - eltData.queuedRequests.push(function () { - issueAjaxRequest(verb, path, elt, event, etc) - }); - } - maybeCall(resolve); - return promise; - } - } - - var xhr = new XMLHttpRequest(); - eltData.xhr = xhr; - eltData.abortable = abortable; - var endRequestLock = function(){ - eltData.xhr = null; - eltData.abortable = false; - if (eltData.queuedRequests != null && - eltData.queuedRequests.length > 0) { - var queuedRequest = eltData.queuedRequests.shift(); - queuedRequest(); - } - } - var promptQuestion = getClosestAttributeValue(elt, "hx-prompt"); - if (promptQuestion) { - var promptResponse = prompt(promptQuestion); - // prompt returns null if cancelled and empty string if accepted with no entry - if (promptResponse === null || - !triggerEvent(elt, 'htmx:prompt', {prompt: promptResponse, target:target})) { - maybeCall(resolve); - endRequestLock(); - return promise; - } - } - - if (confirmQuestion && !confirmed) { - if(!confirm(confirmQuestion)) { - maybeCall(resolve); - endRequestLock() - return promise; - } - } - - - var headers = getHeaders(elt, target, promptResponse); - - if (verb !== 'get' && !usesFormData(elt)) { - headers['Content-Type'] = 'application/x-www-form-urlencoded'; - } - - if (etc.headers) { - headers = mergeObjects(headers, etc.headers); - } - var results = getInputValues(elt, verb); - var errors = results.errors; - var rawParameters = results.values; - if (etc.values) { - rawParameters = mergeObjects(rawParameters, etc.values); - } - var expressionVars = getExpressionVars(elt); - var allParameters = mergeObjects(rawParameters, expressionVars); - var filteredParameters = filterValues(allParameters, elt); - - if (htmx.config.getCacheBusterParam && verb === 'get') { - filteredParameters['org.htmx.cache-buster'] = getRawAttribute(target, "id") || "true"; - } - - // behavior of anchors w/ empty href is to use the current URL - if (path == null || path === "") { - path = getDocument().location.href; - } - - - var requestAttrValues = getValuesForElement(elt, 'hx-request'); - - var eltIsBoosted = getInternalData(elt).boosted; - - var useUrlParams = htmx.config.methodsThatUseUrlParams.indexOf(verb) >= 0 - - var requestConfig = { - boosted: eltIsBoosted, - useUrlParams: useUrlParams, - parameters: filteredParameters, - unfilteredParameters: allParameters, - headers:headers, - target:target, - verb:verb, - errors:errors, - withCredentials: etc.credentials || requestAttrValues.credentials || htmx.config.withCredentials, - timeout: etc.timeout || requestAttrValues.timeout || htmx.config.timeout, - path:path, - triggeringEvent:event - }; - - if(!triggerEvent(elt, 'htmx:configRequest', requestConfig)){ - maybeCall(resolve); - endRequestLock(); - return promise; - } - - // copy out in case the object was overwritten - path = requestConfig.path; - verb = requestConfig.verb; - headers = requestConfig.headers; - filteredParameters = requestConfig.parameters; - errors = requestConfig.errors; - useUrlParams = requestConfig.useUrlParams; - - if(errors && errors.length > 0){ - triggerEvent(elt, 'htmx:validation:halted', requestConfig) - maybeCall(resolve); - endRequestLock(); - return promise; - } - - var splitPath = path.split("#"); - var pathNoAnchor = splitPath[0]; - var anchor = splitPath[1]; - - var finalPath = path - if (useUrlParams) { - finalPath = pathNoAnchor; - var values = Object.keys(filteredParameters).length !== 0; - if (values) { - if (finalPath.indexOf("?") < 0) { - finalPath += "?"; - } else { - finalPath += "&"; - } - finalPath += urlEncode(filteredParameters); - if (anchor) { - finalPath += "#" + anchor; - } - } - } - - if (!verifyPath(elt, finalPath, requestConfig)) { - triggerErrorEvent(elt, 'htmx:invalidPath', requestConfig) - maybeCall(reject); - return promise; - }; - - xhr.open(verb.toUpperCase(), finalPath, true); - xhr.overrideMimeType("text/html"); - xhr.withCredentials = requestConfig.withCredentials; - xhr.timeout = requestConfig.timeout; - - // request headers - if (requestAttrValues.noHeaders) { - // ignore all headers - } else { - for (var header in headers) { - if (headers.hasOwnProperty(header)) { - var headerValue = headers[header]; - safelySetHeaderValue(xhr, header, headerValue); - } - } - } - - var responseInfo = { - xhr: xhr, target: target, requestConfig: requestConfig, etc: etc, boosted: eltIsBoosted, select: select, - pathInfo: { - requestPath: path, - finalRequestPath: finalPath, - anchor: anchor - } - }; - - xhr.onload = function () { - try { - var hierarchy = hierarchyForElt(elt); - responseInfo.pathInfo.responsePath = getPathFromResponse(xhr); - responseHandler(elt, responseInfo); - removeRequestIndicators(indicators, disableElts); - triggerEvent(elt, 'htmx:afterRequest', responseInfo); - triggerEvent(elt, 'htmx:afterOnLoad', responseInfo); - // if the body no longer contains the element, trigger the event on the closest parent - // remaining in the DOM - if (!bodyContains(elt)) { - var secondaryTriggerElt = null; - while (hierarchy.length > 0 && secondaryTriggerElt == null) { - var parentEltInHierarchy = hierarchy.shift(); - if (bodyContains(parentEltInHierarchy)) { - secondaryTriggerElt = parentEltInHierarchy; - } - } - if (secondaryTriggerElt) { - triggerEvent(secondaryTriggerElt, 'htmx:afterRequest', responseInfo); - triggerEvent(secondaryTriggerElt, 'htmx:afterOnLoad', responseInfo); - } - } - maybeCall(resolve); - endRequestLock(); - } catch (e) { - triggerErrorEvent(elt, 'htmx:onLoadError', mergeObjects({error:e}, responseInfo)); - throw e; - } - } - xhr.onerror = function () { - removeRequestIndicators(indicators, disableElts); - triggerErrorEvent(elt, 'htmx:afterRequest', responseInfo); - triggerErrorEvent(elt, 'htmx:sendError', responseInfo); - maybeCall(reject); - endRequestLock(); - } - xhr.onabort = function() { - removeRequestIndicators(indicators, disableElts); - triggerErrorEvent(elt, 'htmx:afterRequest', responseInfo); - triggerErrorEvent(elt, 'htmx:sendAbort', responseInfo); - maybeCall(reject); - endRequestLock(); - } - xhr.ontimeout = function() { - removeRequestIndicators(indicators, disableElts); - triggerErrorEvent(elt, 'htmx:afterRequest', responseInfo); - triggerErrorEvent(elt, 'htmx:timeout', responseInfo); - maybeCall(reject); - endRequestLock(); - } - if(!triggerEvent(elt, 'htmx:beforeRequest', responseInfo)){ - maybeCall(resolve); - endRequestLock() - return promise - } - var indicators = addRequestIndicatorClasses(elt); - var disableElts = disableElements(elt); - - forEach(['loadstart', 'loadend', 'progress', 'abort'], function(eventName) { - forEach([xhr, xhr.upload], function (target) { - target.addEventListener(eventName, function(event){ - triggerEvent(elt, "htmx:xhr:" + eventName, { - lengthComputable:event.lengthComputable, - loaded:event.loaded, - total:event.total - }); - }) - }); - }); - triggerEvent(elt, 'htmx:beforeSend', responseInfo); - var params = useUrlParams ? null : encodeParamsForBody(xhr, elt, filteredParameters) - xhr.send(params); - return promise; - } - - function determineHistoryUpdates(elt, responseInfo) { - - var xhr = responseInfo.xhr; - - //=========================================== - // First consult response headers - //=========================================== - var pathFromHeaders = null; - var typeFromHeaders = null; - if (hasHeader(xhr,/HX-Push:/i)) { - pathFromHeaders = xhr.getResponseHeader("HX-Push"); - typeFromHeaders = "push"; - } else if (hasHeader(xhr,/HX-Push-Url:/i)) { - pathFromHeaders = xhr.getResponseHeader("HX-Push-Url"); - typeFromHeaders = "push"; - } else if (hasHeader(xhr,/HX-Replace-Url:/i)) { - pathFromHeaders = xhr.getResponseHeader("HX-Replace-Url"); - typeFromHeaders = "replace"; - } - - // if there was a response header, that has priority - if (pathFromHeaders) { - if (pathFromHeaders === "false") { - return {} - } else { - return { - type: typeFromHeaders, - path : pathFromHeaders - } - } - } - - //=========================================== - // Next resolve via DOM values - //=========================================== - var requestPath = responseInfo.pathInfo.finalRequestPath; - var responsePath = responseInfo.pathInfo.responsePath; - - var pushUrl = getClosestAttributeValue(elt, "hx-push-url"); - var replaceUrl = getClosestAttributeValue(elt, "hx-replace-url"); - var elementIsBoosted = getInternalData(elt).boosted; - - var saveType = null; - var path = null; - - if (pushUrl) { - saveType = "push"; - path = pushUrl; - } else if (replaceUrl) { - saveType = "replace"; - path = replaceUrl; - } else if (elementIsBoosted) { - saveType = "push"; - path = responsePath || requestPath; // if there is no response path, go with the original request path - } - - if (path) { - // false indicates no push, return empty object - if (path === "false") { - return {}; - } - - // true indicates we want to follow wherever the server ended up sending us - if (path === "true") { - path = responsePath || requestPath; // if there is no response path, go with the original request path - } - - // restore any anchor associated with the request - if (responseInfo.pathInfo.anchor && - path.indexOf("#") === -1) { - path = path + "#" + responseInfo.pathInfo.anchor; - } - - return { - type:saveType, - path: path - } - } else { - return {}; - } - } - - function handleAjaxResponse(elt, responseInfo) { - var xhr = responseInfo.xhr; - var target = responseInfo.target; - var etc = responseInfo.etc; - var requestConfig = responseInfo.requestConfig; - var select = responseInfo.select; - - if (!triggerEvent(elt, 'htmx:beforeOnLoad', responseInfo)) return; - - if (hasHeader(xhr, /HX-Trigger:/i)) { - handleTrigger(xhr, "HX-Trigger", elt); - } - - if (hasHeader(xhr, /HX-Location:/i)) { - saveCurrentPageToHistory(); - var redirectPath = xhr.getResponseHeader("HX-Location"); - var swapSpec; - if (redirectPath.indexOf("{") === 0) { - swapSpec = parseJSON(redirectPath); - // what's the best way to throw an error if the user didn't include this - redirectPath = swapSpec['path']; - delete swapSpec['path']; - } - ajaxHelper('GET', redirectPath, swapSpec).then(function(){ - pushUrlIntoHistory(redirectPath); - }); - return; - } - - var shouldRefresh = hasHeader(xhr, /HX-Refresh:/i) && "true" === xhr.getResponseHeader("HX-Refresh"); - - if (hasHeader(xhr, /HX-Redirect:/i)) { - location.href = xhr.getResponseHeader("HX-Redirect"); - shouldRefresh && location.reload(); - return; - } - - if (shouldRefresh) { - location.reload(); - return; - } - - if (hasHeader(xhr,/HX-Retarget:/i)) { - if (xhr.getResponseHeader("HX-Retarget") === "this") { - responseInfo.target = elt; - } else { - responseInfo.target = querySelectorExt(elt, xhr.getResponseHeader("HX-Retarget")); - } - } - - var historyUpdate = determineHistoryUpdates(elt, responseInfo); - - // by default htmx only swaps on 200 return codes and does not swap - // on 204 'No Content' - // this can be ovverriden by responding to the htmx:beforeSwap event and - // overriding the detail.shouldSwap property - var shouldSwap = xhr.status >= 200 && xhr.status < 400 && xhr.status !== 204; - var serverResponse = xhr.response; - var isError = xhr.status >= 400; - var ignoreTitle = htmx.config.ignoreTitle - var beforeSwapDetails = mergeObjects({shouldSwap: shouldSwap, serverResponse:serverResponse, isError:isError, ignoreTitle:ignoreTitle }, responseInfo); - if (!triggerEvent(target, 'htmx:beforeSwap', beforeSwapDetails)) return; - - target = beforeSwapDetails.target; // allow re-targeting - serverResponse = beforeSwapDetails.serverResponse; // allow updating content - isError = beforeSwapDetails.isError; // allow updating error - ignoreTitle = beforeSwapDetails.ignoreTitle; // allow updating ignoring title - - responseInfo.target = target; // Make updated target available to response events - responseInfo.failed = isError; // Make failed property available to response events - responseInfo.successful = !isError; // Make successful property available to response events - - if (beforeSwapDetails.shouldSwap) { - if (xhr.status === 286) { - cancelPolling(elt); - } - - withExtensions(elt, function (extension) { - serverResponse = extension.transformResponse(serverResponse, xhr, elt); - }); - - // Save current page if there will be a history update - if (historyUpdate.type) { - saveCurrentPageToHistory(); - } - - var swapOverride = etc.swapOverride; - if (hasHeader(xhr,/HX-Reswap:/i)) { - swapOverride = xhr.getResponseHeader("HX-Reswap"); - } - var swapSpec = getSwapSpecification(elt, swapOverride); - - if (swapSpec.hasOwnProperty('ignoreTitle')) { - ignoreTitle = swapSpec.ignoreTitle; - } - - target.classList.add(htmx.config.swappingClass); - - // optional transition API promise callbacks - var settleResolve = null; - var settleReject = null; - - var doSwap = function () { - try { - var activeElt = document.activeElement; - var selectionInfo = {}; - try { - selectionInfo = { - elt: activeElt, - // @ts-ignore - start: activeElt ? activeElt.selectionStart : null, - // @ts-ignore - end: activeElt ? activeElt.selectionEnd : null - }; - } catch (e) { - // safari issue - see https://github.com/microsoft/playwright/issues/5894 - } - - var selectOverride; - if (select) { - selectOverride = select; - } - - if (hasHeader(xhr, /HX-Reselect:/i)) { - selectOverride = xhr.getResponseHeader("HX-Reselect"); - } - - // if we need to save history, do so, before swapping so that relative resources have the correct base URL - if (historyUpdate.type) { - triggerEvent(getDocument().body, 'htmx:beforeHistoryUpdate', mergeObjects({ history: historyUpdate }, responseInfo)); - if (historyUpdate.type === "push") { - pushUrlIntoHistory(historyUpdate.path); - triggerEvent(getDocument().body, 'htmx:pushedIntoHistory', {path: historyUpdate.path}); - } else { - replaceUrlInHistory(historyUpdate.path); - triggerEvent(getDocument().body, 'htmx:replacedInHistory', {path: historyUpdate.path}); - } - } - - var settleInfo = makeSettleInfo(target); - selectAndSwap(swapSpec.swapStyle, target, elt, serverResponse, settleInfo, selectOverride); - - if (selectionInfo.elt && - !bodyContains(selectionInfo.elt) && - getRawAttribute(selectionInfo.elt, "id")) { - var newActiveElt = document.getElementById(getRawAttribute(selectionInfo.elt, "id")); - var focusOptions = { preventScroll: swapSpec.focusScroll !== undefined ? !swapSpec.focusScroll : !htmx.config.defaultFocusScroll }; - if (newActiveElt) { - // @ts-ignore - if (selectionInfo.start && newActiveElt.setSelectionRange) { - // @ts-ignore - try { - newActiveElt.setSelectionRange(selectionInfo.start, selectionInfo.end); - } catch (e) { - // the setSelectionRange method is present on fields that don't support it, so just let this fail - } - } - newActiveElt.focus(focusOptions); - } - } - - target.classList.remove(htmx.config.swappingClass); - forEach(settleInfo.elts, function (elt) { - if (elt.classList) { - elt.classList.add(htmx.config.settlingClass); - } - triggerEvent(elt, 'htmx:afterSwap', responseInfo); - }); - - if (hasHeader(xhr, /HX-Trigger-After-Swap:/i)) { - var finalElt = elt; - if (!bodyContains(elt)) { - finalElt = getDocument().body; - } - handleTrigger(xhr, "HX-Trigger-After-Swap", finalElt); - } - - var doSettle = function () { - forEach(settleInfo.tasks, function (task) { - task.call(); - }); - forEach(settleInfo.elts, function (elt) { - if (elt.classList) { - elt.classList.remove(htmx.config.settlingClass); - } - triggerEvent(elt, 'htmx:afterSettle', responseInfo); - }); - - if (responseInfo.pathInfo.anchor) { - var anchorTarget = getDocument().getElementById(responseInfo.pathInfo.anchor); - if(anchorTarget) { - anchorTarget.scrollIntoView({block:'start', behavior: "auto"}); - } - } - - if(settleInfo.title && !ignoreTitle) { - var titleElt = find("title"); - if(titleElt) { - titleElt.innerHTML = settleInfo.title; - } else { - window.document.title = settleInfo.title; - } - } - - updateScrollState(settleInfo.elts, swapSpec); - - if (hasHeader(xhr, /HX-Trigger-After-Settle:/i)) { - var finalElt = elt; - if (!bodyContains(elt)) { - finalElt = getDocument().body; - } - handleTrigger(xhr, "HX-Trigger-After-Settle", finalElt); - } - maybeCall(settleResolve); - } - - if (swapSpec.settleDelay > 0) { - setTimeout(doSettle, swapSpec.settleDelay) - } else { - doSettle(); - } - } catch (e) { - triggerErrorEvent(elt, 'htmx:swapError', responseInfo); - maybeCall(settleReject); - throw e; - } - }; - - var shouldTransition = htmx.config.globalViewTransitions - if(swapSpec.hasOwnProperty('transition')){ - shouldTransition = swapSpec.transition; - } - - if(shouldTransition && - triggerEvent(elt, 'htmx:beforeTransition', responseInfo) && - typeof Promise !== "undefined" && document.startViewTransition){ - var settlePromise = new Promise(function (_resolve, _reject) { - settleResolve = _resolve; - settleReject = _reject; - }); - // wrap the original doSwap() in a call to startViewTransition() - var innerDoSwap = doSwap; - doSwap = function() { - document.startViewTransition(function () { - innerDoSwap(); - return settlePromise; - }); - } - } - - - if (swapSpec.swapDelay > 0) { - setTimeout(doSwap, swapSpec.swapDelay) - } else { - doSwap(); - } - } - if (isError) { - triggerErrorEvent(elt, 'htmx:responseError', mergeObjects({error: "Response Status Error Code " + xhr.status + " from " + responseInfo.pathInfo.requestPath}, responseInfo)); - } - } - - //==================================================================== - // Extensions API - //==================================================================== - - /** @type {Object} */ - var extensions = {}; - - /** - * extensionBase defines the default functions for all extensions. - * @returns {import("./htmx").HtmxExtension} - */ - function extensionBase() { - return { - init: function(api) {return null;}, - onEvent : function(name, evt) {return true;}, - transformResponse : function(text, xhr, elt) {return text;}, - isInlineSwap : function(swapStyle) {return false;}, - handleSwap : function(swapStyle, target, fragment, settleInfo) {return false;}, - encodeParameters : function(xhr, parameters, elt) {return null;} - } - } - - /** - * defineExtension initializes the extension and adds it to the htmx registry - * - * @param {string} name - * @param {import("./htmx").HtmxExtension} extension - */ - function defineExtension(name, extension) { - if(extension.init) { - extension.init(internalAPI) - } - extensions[name] = mergeObjects(extensionBase(), extension); - } - - /** - * removeExtension removes an extension from the htmx registry - * - * @param {string} name - */ - function removeExtension(name) { - delete extensions[name]; - } - - /** - * getExtensions searches up the DOM tree to return all extensions that can be applied to a given element - * - * @param {HTMLElement} elt - * @param {import("./htmx").HtmxExtension[]=} extensionsToReturn - * @param {import("./htmx").HtmxExtension[]=} extensionsToIgnore - */ - function getExtensions(elt, extensionsToReturn, extensionsToIgnore) { - - if (elt == undefined) { - return extensionsToReturn; - } - if (extensionsToReturn == undefined) { - extensionsToReturn = []; - } - if (extensionsToIgnore == undefined) { - extensionsToIgnore = []; - } - var extensionsForElement = getAttributeValue(elt, "hx-ext"); - if (extensionsForElement) { - forEach(extensionsForElement.split(","), function(extensionName){ - extensionName = extensionName.replace(/ /g, ''); - if (extensionName.slice(0, 7) == "ignore:") { - extensionsToIgnore.push(extensionName.slice(7)); - return; - } - if (extensionsToIgnore.indexOf(extensionName) < 0) { - var extension = extensions[extensionName]; - if (extension && extensionsToReturn.indexOf(extension) < 0) { - extensionsToReturn.push(extension); - } - } - }); - } - return getExtensions(parentElt(elt), extensionsToReturn, extensionsToIgnore); - } - - //==================================================================== - // Initialization - //==================================================================== - var isReady = false - getDocument().addEventListener('DOMContentLoaded', function() { - isReady = true - }) - - /** - * Execute a function now if DOMContentLoaded has fired, otherwise listen for it. - * - * This function uses isReady because there is no realiable way to ask the browswer whether - * the DOMContentLoaded event has already been fired; there's a gap between DOMContentLoaded - * firing and readystate=complete. - */ - function ready(fn) { - // Checking readyState here is a failsafe in case the htmx script tag entered the DOM by - // some means other than the initial page load. - if (isReady || getDocument().readyState === 'complete') { - fn(); - } else { - getDocument().addEventListener('DOMContentLoaded', fn); - } - } - - function insertIndicatorStyles() { - if (htmx.config.includeIndicatorStyles !== false) { - getDocument().head.insertAdjacentHTML("beforeend", - ""); - } - } - - function getMetaConfig() { - var element = getDocument().querySelector('meta[name="htmx-config"]'); - if (element) { - // @ts-ignore - return parseJSON(element.content); - } else { - return null; - } - } - - function mergeMetaConfig() { - var metaConfig = getMetaConfig(); - if (metaConfig) { - htmx.config = mergeObjects(htmx.config , metaConfig) - } - } - - // initialize the document - ready(function () { - mergeMetaConfig(); - insertIndicatorStyles(); - var body = getDocument().body; - processNode(body); - var restoredElts = getDocument().querySelectorAll( - "[hx-trigger='restored'],[data-hx-trigger='restored']" - ); - body.addEventListener("htmx:abort", function (evt) { - var target = evt.target; - var internalData = getInternalData(target); - if (internalData && internalData.xhr) { - internalData.xhr.abort(); - } - }); - /** @type {(ev: PopStateEvent) => any} */ - const originalPopstate = window.onpopstate ? window.onpopstate.bind(window) : null; - /** @type {(ev: PopStateEvent) => any} */ - window.onpopstate = function (event) { - if (event.state && event.state.htmx) { - restoreHistory(); - forEach(restoredElts, function(elt){ - triggerEvent(elt, 'htmx:restored', { - 'document': getDocument(), - 'triggerEvent': triggerEvent - }); - }); - } else { - if (originalPopstate) { - originalPopstate(event); - } - } - }; - setTimeout(function () { - triggerEvent(body, 'htmx:load', {}); // give ready handlers a chance to load up before firing this event - body = null; // kill reference for gc - }, 0); - }) - - return htmx; - } -)() -})); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-boost.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-boost.js deleted file mode 100644 index f8698a330be..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-boost.js +++ /dev/null @@ -1,118 +0,0 @@ -describe("hx-boost attribute", function() { - - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it('handles basic anchor properly', function () { - this.server.respondWith("GET", "/test", "Boosted"); - var div = make(''); - var a = byId('a1'); - a.click(); - this.server.respond(); - div.innerHTML.should.equal("Boosted"); - }) - - - it('handles basic form post properly', function () { - this.server.respondWith("POST", "/test", "Boosted"); - var div = make('
    '); - var btn = byId('b1'); - btn.click(); - this.server.respond(); - div.innerHTML.should.equal("Boosted"); - }) - - it('handles basic form post with button formaction properly', function () { - this.server.respondWith("POST", "/test", "Boosted"); - var div = make('
    '); - var btn = byId('b1'); - btn.click(); - this.server.respond(); - div.innerHTML.should.equal("Boosted"); - }) - - it('handles basic form post with button formmethod properly', function () { - this.server.respondWith("POST", "/test", "Boosted"); - var div = make('
    '); - var btn = byId('b1'); - btn.click(); - this.server.respond(); - div.innerHTML.should.equal("Boosted"); - }) - - it('handles basic form post properly w/ explicit action', function () { - this.server.respondWith("POST", "/test", "Boosted"); - var div = make('
    '); - var form = byId('f1'); - form.click(); - this.server.respond(); - div.innerHTML.should.equal("Boosted"); - }) - - it('handles basic form get properly', function () { - this.server.respondWith("GET", "/test", "Boosted"); - var div = make('
    '); - var btn = byId('b1'); - btn.click(); - this.server.respond(); - div.innerHTML.should.equal("Boosted"); - }) - - it('handles basic form with no explicit method property', function () { - this.server.respondWith("GET", "/test", "Boosted"); - var div = make('
    '); - var btn = byId('b1'); - btn.click(); - this.server.respond(); - div.innerHTML.should.equal("Boosted"); - }) - - it('handles basic anchor properly w/ data-* prefix', function () { - this.server.respondWith("GET", "/test", "Boosted"); - var div = make(''); - var a = byId('a1'); - a.click(); - this.server.respond(); - div.innerHTML.should.equal("Boosted"); - }) - - - it('overriding default swap style does not effect boosting', function () { - htmx.config.defaultSwapStyle = "afterend"; - try { - this.server.respondWith("GET", "/test", "Boosted"); - var a = make('Foo'); - a.click(); - this.server.respond(); - a.innerHTML.should.equal("Boosted"); - } finally { - htmx.config.defaultSwapStyle = "innerHTML"; - } - }) - - it('anchors w/ explicit targets are not boosted', function () { - var a = make('Foo'); - var internalData = htmx._("getInternalData")(a); - should.equal(undefined, internalData.boosted); - }) - - it('includes an HX-Boosted Header', function() - { - this.server.respondWith("GET", "/test", function(xhr){ - should.equal(xhr.requestHeaders['HX-Boosted'], "true"); - xhr.respond(200, {}, "Boosted!"); - }); - - var btn = make('Click Me!') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Boosted!"); - }); - -}); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-confirm.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-confirm.js deleted file mode 100644 index 7f8516d7b43..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-confirm.js +++ /dev/null @@ -1,126 +0,0 @@ -describe("hx-confirm attribute", function () { - var confirm - beforeEach(function () { - this.server = makeServer(); - confirm = sinon.stub(window, "confirm"); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - confirm.restore() - clearWorkArea(); - }); - - it('prompts using window.confirm when hx-confirm is set', function () { - this.server.respondWith("GET", "/test", "Clicked!"); - confirm.returns(true); - var btn = make('') - btn.click(); - confirm.calledOnce.should.equal(true); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - }) - - it('stops the request if confirm is cancelled', function () { - this.server.respondWith("GET", "/test", "Clicked!"); - confirm.returns(false); - var btn = make('') - btn.click(); - confirm.calledOnce.should.equal(true); - this.server.respond(); - btn.innerHTML.should.equal("Click Me!"); - }) - - it('uses the value of hx-confirm as the prompt', function () { - this.server.respondWith("GET", "/test", "Clicked!"); - confirm.returns(false); - var btn = make('') - btn.click(); - confirm.firstCall.args[0].should.equal("Sure?"); - this.server.respond(); - btn.innerHTML.should.equal("Click Me!"); - }) - - it('should prompt when htmx:confirm handler calls issueRequest', function () { - try { - var btn = make('') - var handler = htmx.on("htmx:confirm", function (evt) { - evt.preventDefault(); - evt.detail.issueRequest(); - }); - btn.click(); - confirm.calledOnce.should.equal(true); - } finally { - htmx.off("htmx:confirm", handler); - } - }) - - it('should include the question in htmx:confirm event', function () { - var stub = sinon.stub(); - try { - var btn = make('') - var handler = htmx.on("htmx:confirm", stub); - btn.click(); - stub.calledOnce.should.equal(true); - stub.firstCall.args[0].detail.should.have.property("question", "Surely?"); - } finally { - htmx.off("htmx:confirm", handler); - } - }) - - it('should allow skipping built-in window.confirm when using issueRequest', function () { - this.server.respondWith("GET", "/test", "Clicked!"); - try { - var btn = make('') - var handler = htmx.on("htmx:confirm", function (evt) { - evt.detail.question.should.equal("Sure?"); - evt.preventDefault(); - evt.detail.issueRequest(true); - }); - btn.click(); - confirm.called.should.equal(false); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - } finally { - htmx.off("htmx:confirm", handler); - } - }) - it('should allow skipping built-in window.confirm when using issueRequest', function () { - this.server.respondWith("GET", "/test", "Clicked!"); - try { - var btn = make('') - var handler = htmx.on("htmx:confirm", function (evt) { - evt.detail.question.should.equal("Sure?"); - evt.preventDefault(); - evt.detail.issueRequest(true); - }); - btn.click(); - confirm.called.should.equal(false); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - } finally { - htmx.off("htmx:confirm", handler); - } - }) - - - it('should allow htmx:confirm even when no hx-confirm is set', function () { - this.server.respondWith("GET", "/test", "Clicked!"); - try { - var btn = make('') - var handler = htmx.on("htmx:confirm", function (evt) { - evt.detail.should.have.property("question", null); - evt.preventDefault(); - evt.detail.issueRequest(); - }); - btn.click(); - confirm.called.should.equal(false); // no hx-confirm means no window.confirm - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - } finally { - htmx.off("htmx:confirm", handler); - } - }) - - -}); \ No newline at end of file diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-delete.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-delete.js deleted file mode 100644 index 22b0f7607af..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-delete.js +++ /dev/null @@ -1,34 +0,0 @@ -describe("hx-delete attribute", function(){ - beforeEach(function() { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function() { - this.server.restore(); - clearWorkArea(); - }); - - it('issues a DELETE request', function() - { - this.server.respondWith("DELETE", "/test", function(xhr){ - xhr.respond(200, {}, "Deleted!"); - }); - - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Deleted!"); - }); - - it('issues a DELETE request w/ data-* prefix', function() - { - this.server.respondWith("DELETE", "/test", function(xhr){ - xhr.respond(200, {}, "Deleted!"); - }); - - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Deleted!"); - }); -}) diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-disabled-elt.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-disabled-elt.js deleted file mode 100644 index dac6bb7b0ad..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-disabled-elt.js +++ /dev/null @@ -1,94 +0,0 @@ -describe("hx-disabled-elt attribute", function(){ - beforeEach(function() { - this.server = sinon.fakeServer.create(); - clearWorkArea(); - }); - afterEach(function() { - this.server.restore(); - clearWorkArea(); - }); - - it('single element can be disabled w/ hx-disabled elts', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - var btn = make('') - btn.hasAttribute('disabled').should.equal(false); - btn.click(); - btn.hasAttribute('disabled').should.equal(true); - this.server.respond(); - btn.hasAttribute('disabled').should.equal(false); - }); - - - it('single element can be disabled w/ data-hx-disabled elts', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - var btn = make('') - btn.hasAttribute('disabled').should.equal(false); - btn.click(); - btn.hasAttribute('disabled').should.equal(true); - this.server.respond(); - btn.hasAttribute('disabled').should.equal(false); - }); - - it('single element can be disabled w/ closest syntax', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - var fieldset = make('
    ') - var btn = byId('b1'); - fieldset.hasAttribute('disabled').should.equal(false); - btn.click(); - fieldset.hasAttribute('disabled').should.equal(true); - this.server.respond(); - fieldset.hasAttribute('disabled').should.equal(false); - }); - - it('multiple requests with same disabled elt are handled properly', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - var b1 = make('') - var b2 = make('') - var b3 = make('') - b3.hasAttribute('disabled').should.equal(false); - - b1.click(); - b3.hasAttribute('disabled').should.equal(true); - - b2.click(); - b3.hasAttribute('disabled').should.equal(true); - - - // hack to make sinon process only one response - this.server.processRequest(this.server.queue.shift()); - - b3.hasAttribute('disabled').should.equal(true); - - this.server.respond(); - - b3.hasAttribute('disabled').should.equal(false); - - }); - - it('multiple elts can be disabled', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - var b1 = make('') - var b2 = make('') - var b3 = make('') - - b2.hasAttribute('disabled').should.equal(false); - b3.hasAttribute('disabled').should.equal(false); - - b1.click(); - b2.hasAttribute('disabled').should.equal(true); - b3.hasAttribute('disabled').should.equal(true); - - this.server.respond(); - - b2.hasAttribute('disabled').should.equal(false); - b3.hasAttribute('disabled').should.equal(false); - - }); - - -}) diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-disinherit.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-disinherit.js deleted file mode 100644 index 4b663e75139..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-disinherit.js +++ /dev/null @@ -1,151 +0,0 @@ -describe("hx-disinherit attribute", function() { - - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it('basic inheritance sanity-check', function () { - var response_inner = '
    Hello world
    ' - var response = '
    ' + response_inner + '
    ' - this.server.respondWith("GET", "/test", response); - - var div = make('
    ') - var btn = byId("bx1"); - btn.click(); - this.server.respond(); - btn.firstChild.id.should.equal("snowflake"); - btn.innerText.should.equal("Hello world"); - }) - - - it('disinherit exclude single attribute', function () { - var response_inner = '
    Hello world
    ' - var response = '
    ' + response_inner + '
    ' - this.server.respondWith("GET", "/test", response); - - var div = make('
    ') - var btn = byId("bx1"); - btn.click(); - this.server.respond(); - btn.firstChild.id.should.equal("unique") - btn.firstChild.firstChild.id.should.equal("snowflake") - btn.childNodes[1].innerText.should.equal("Click Me!") - }); - - it('disinherit exclude multiple attributes', function () { - var response_inner = '
    Hello world
    ' - var response = '
    ' + response_inner + '
    ' - this.server.respondWith("GET", "/test", response); - - var div = make('
    ' + - ' ' + - '
    ') - var btn = byId("bx1"); - btn.click(); - this.server.respond(); - console.log(btn.innerHTML); - console.log(response); - btn.firstChild.id.should.equal("cta") - btn.firstChild.firstChild.id.should.equal("unique") - btn.firstChild.firstChild.firstChild.id.should.equal("snowflake") - }); - - it('disinherit exclude all attributes', function () { - var response_inner = '
    Hello world
    ' - var response = '
    ' + response_inner + '
    ' - this.server.respondWith("GET", "/test", response); - var div = make('
    ' + - ' ' + - '
    ') - var btn = byId("bx1"); - btn.click(); - this.server.respond(); - btn.firstChild.id.should.equal("unique"); - btn.firstChild.firstChild.id.should.equal("snowflake"); - }); - - it('same-element inheritance disable', function () { - var response_inner = '
    Hello world
    ' - var response = '
    ' + response_inner + '
    ' - this.server.respondWith("GET", "/test", response); - - var btn = make('') - btn.click(); - this.server.respond(); - btn.firstChild.id.should.equal("snowflake"); - btn.firstChild.innerText.should.equal("Hello world"); - }); - - it('same-element inheritance disable with child nodes', function () { - var response_inner = '
    Hello world
    ' - var response = '
    ' + response_inner + '
    ' - this.server.respondWith("GET", "/test", response); - this.server.respondWith("GET", "/test2", 'unique-snowflake'); - - var div = make('
    ') - var btn = byId("bx1"); - btn.click(); - this.server.respond(); - btn.firstChild.id.should.equal('target'); - btn.firstChild.innerText.should.equal('unique-snowflake'); - var count = (div.parentElement.innerHTML.match(/snowflake/g) || []).length; - count.should.equal(2); // hx-select of parent div and newly loaded inner content - }); - - it('boosted element hx-disinherit sanity check', function () { - try { - var request; - var handler = htmx.on("htmx:beforeRequest", function (evt) { - request = evt; - }); - var div = make(''); - var link = byId("a1"); - link.click(); - // should match the fully resolved href of the boosted element - should.equal(request.detail.requestConfig.path, '/test'); - should.equal(request.detail.elt["htmx-internal-data"].boosted, true); - } finally { - htmx.off("htmx:beforeRequest", handler); - } - }); - - it('boosted element inheritance manual unset', function () { - try { - var request; - var handler = htmx.on("htmx:beforeRequest", function (evt) { - request = evt; - }); - var div = make(''); - var link = byId("a1"); - should.equal(link["htmx-internal-data"].boosted, undefined); - } finally { - htmx.off("htmx:beforeRequest", handler); - } - }); - - it('nested htmx-node with boosting parent', function () { - try { - var request; - var handler = htmx.on("htmx:beforeRequest", function (evt) { - request = evt; - }); - var div = make(''); - var link = byId("a1"); - link.click(); - should.equal(request.detail.requestConfig.path, '/test2'); - should.equal(request.detail.elt["htmx-internal-data"].boosted, undefined); - should.equal(request.detail.target.id, "a1"); - } finally { - htmx.off("htmx:beforeRequest", handler); - } - }); - -}); - diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-ext.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-ext.js deleted file mode 100644 index 740b9bd8b73..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-ext.js +++ /dev/null @@ -1,138 +0,0 @@ -describe("hx-ext attribute", function() { - - var ext1Calls, ext2Calls, ext3Calls, ext4Calls; - - beforeEach(function () { - ext1Calls = ext2Calls = ext3Calls = ext4Calls = 0; - this.server = makeServer(); - clearWorkArea(); - htmx.defineExtension("ext-1", { - onEvent : function(name, evt) { - if(name === "htmx:afterRequest"){ - ext1Calls++; - } - } - }); - htmx.defineExtension("ext-2", { - onEvent : function(name, evt) { - if(name === "htmx:afterRequest"){ - ext2Calls++; - } - } - }); - htmx.defineExtension("ext-3", { - onEvent : function(name, evt) { - if(name === "htmx:afterRequest"){ - ext3Calls++; - } - } - }); - htmx.defineExtension("ext-4", { - onEvent : function(name, evt) { - if(name === "namespace:example"){ - ext4Calls++; - } - } - }); - }); - - afterEach(function () { - this.server.restore(); - clearWorkArea(); - htmx.removeExtension("ext-1"); - htmx.removeExtension("ext-2"); - htmx.removeExtension("ext-3"); - }); - - it('A simple extension is invoked properly', function () { - this.server.respondWith("GET", "/test", "Clicked!"); - - var btn = make('') - btn.click(); - this.server.respond(); - ext1Calls.should.equal(1); - ext2Calls.should.equal(0); - ext3Calls.should.equal(0); - }); - - it('Extensions are merged properly', function () { - this.server.respondWith("GET", "/test", "Clicked!"); - - make('
    ' + - '
    ') - var btn1 = byId("btn-1"); - var btn2 = byId("btn-2"); - - btn1.click(); - this.server.respond(); - ext1Calls.should.equal(1); - ext2Calls.should.equal(1); - ext3Calls.should.equal(0); - - btn2.click(); - this.server.respond(); - ext1Calls.should.equal(2); - ext2Calls.should.equal(1); - ext3Calls.should.equal(1); - }); - - it('supports comma separated lists', function () { - this.server.respondWith("GET", "/test", "Clicked!"); - - make('
    ') - var btn1 = byId("btn-1"); - var btn2 = byId("btn-2"); - - btn1.click(); - this.server.respond(); - ext1Calls.should.equal(1); - ext2Calls.should.equal(1); - ext3Calls.should.equal(1); - }); - - it('A simple extension is invoked properly w/ data-* prefix', function () { - this.server.respondWith("GET", "/test", "Clicked!"); - - var btn = make('') - btn.click(); - this.server.respond(); - ext1Calls.should.equal(1); - ext2Calls.should.equal(0); - ext3Calls.should.equal(0); - }); - - it('A simple extension is invoked properly when an HX-Trigger event w/ a namespace fires', function () { - this.server.respondWith("GET", "/test", [200, {"HX-Trigger":"namespace:example"}, ""]); - var btn = make('') - btn.click(); - this.server.respond(); - ext1Calls.should.equal(0); - ext2Calls.should.equal(0); - ext3Calls.should.equal(0); - ext4Calls.should.equal(1); - - }); - - it('Extensions are ignored properly', function () { - this.server.respondWith("GET", "/test", "Clicked!"); - - make('
    ' + - '
    ') - - var btn1 = byId("btn-AA"); - var btn2 = byId("btn-BB"); - - btn1.click(); - this.server.respond(); - ext1Calls.should.equal(1); - ext2Calls.should.equal(1); - ext3Calls.should.equal(0); - - btn2.click(); - this.server.respond(); - ext1Calls.should.equal(1); - ext2Calls.should.equal(2); - ext3Calls.should.equal(0); - }) - -}); \ No newline at end of file diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-get.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-get.js deleted file mode 100644 index 8b0a6db9a2d..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-get.js +++ /dev/null @@ -1,129 +0,0 @@ -describe("hx-get attribute", function() { - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it('issues a GET request on click and swaps content', function () { - this.server.respondWith("GET", "/test", "Clicked!"); - - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - }); - - it('GET does not include surrounding data by default', function () { - this.server.respondWith("GET", "/test", function (xhr) { - should.equal(getParameters(xhr)["i1"], undefined); - xhr.respond(200, {}, "Clicked!"); - }); - make('
    ') - var btn = byId("b1"); - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - }); - - it('GET on form includes its own data by default', function () { - this.server.respondWith("GET", /\/test.*/, function (xhr) { - getParameters(xhr)["i1"].should.equal("value"); - xhr.respond(200, {}, "Clicked!"); - }); - var form = make('
    '); - form.click(); - this.server.respond(); - form.innerHTML.should.equal("Clicked!"); - }); - - it('GET on form with existing parameters works properly', function () { - this.server.respondWith("GET", /\/test.*/, function (xhr) { - getParameters(xhr)["foo"].should.equal("bar"); - getParameters(xhr)["i1"].should.equal("value"); - xhr.respond(200, {}, "Clicked!"); - }); - var form = make('
    '); - form.click(); - this.server.respond(); - form.innerHTML.should.equal("Clicked!"); - }); - - it('GET on form with anchor works properly', function () { - this.server.respondWith("GET", /\/test.*/, function (xhr) { - getParameters(xhr)["foo"].should.equal("bar"); - getParameters(xhr)["i1"].should.equal("value"); - xhr.respond(200, {}, "Clicked!"); - }); - var form = make('
    '); - form.click(); - this.server.respond(); - form.innerHTML.should.equal("Clicked!"); - }); - - - it('issues a GET request on click and swaps content w/ data-* prefix', function () { - this.server.respondWith("GET", "/test", "Clicked!"); - - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - }); - - it('does not include a cache-busting parameter when not enabled', function () { - - this.server.respondWith("GET", /\/test.*/, function (xhr) { - should.not.exist(getParameters(xhr)["org.htmx.cache-buster"]); - xhr.respond(200, {}, "Clicked!"); - }); - - try { - htmx.config.getCacheBusterParam = false; - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - } finally { - htmx.config.getCacheBusterParam = false; - } - }); - - it('includes a cache-busting parameter when enabled w/ value "true" if no id on target', function () { - - this.server.respondWith("GET", /\/test.*/, function (xhr) { - getParameters(xhr)["org.htmx.cache-buster"].should.equal("true"); - xhr.respond(200, {}, "Clicked!"); - }); - - try { - htmx.config.getCacheBusterParam = true; - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - } finally { - htmx.config.getCacheBusterParam = false; - } - }); - - it('includes a cache-busting parameter when enabled w/ the id of the target if there is one', function () { - this.server.respondWith("GET", /\/test.*/, function (xhr) { - getParameters(xhr)["org.htmx.cache-buster"].should.equal("foo"); - xhr.respond(200, {}, "Clicked!"); - }); - - try { - htmx.config.getCacheBusterParam = true; - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - } finally { - htmx.config.getCacheBusterParam = false; - } - }); -}); \ No newline at end of file diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-headers.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-headers.js deleted file mode 100644 index 0333533ca64..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-headers.js +++ /dev/null @@ -1,164 +0,0 @@ -describe("hx-headers attribute", function() { - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it('basic hx-headers works', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - - xhr.requestHeaders['i1'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make("
    ") - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('basic hx-headers works with braces', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - - xhr.requestHeaders['i1'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make("
    ") - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('multiple hx-headers works', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - - xhr.requestHeaders['v1'].should.equal("test"); - xhr.requestHeaders['v2'].should.equal("42"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make("
    ") - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('hx-headers can be on parents', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - - xhr.requestHeaders['i1'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - make("
    "); - var div = byId("d1"); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('hx-headers can override parents', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - - xhr.requestHeaders['i1'].should.equal("best"); - xhr.respond(200, {}, "Clicked!") - }); - make("
    "); - var div = byId("d1"); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('hx-headers overrides inputs', function () { - this.server.respondWith("POST", "/include", function (xhr) { - - xhr.requestHeaders['i1'].should.equal("best"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make("
    ") - var input = byId("i1") - input.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('basic hx-headers javascript: works', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - - xhr.requestHeaders['i1'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make('
    ') - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('hx-headers works with braces', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - - xhr.requestHeaders['i1'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make('
    ') - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('multiple hx-headers works', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - - xhr.requestHeaders['v1'].should.equal("test"); - xhr.requestHeaders['v2'].should.equal("42"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make('
    ') - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('hx-headers can be on parents', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - - xhr.requestHeaders['i1'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - make('
    ') - var div = byId("d1"); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('hx-headers can override parents', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - - xhr.requestHeaders['i1'].should.equal("best"); - xhr.respond(200, {}, "Clicked!") - }); - make('
    ') - var div = byId("d1"); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('hx-headers overrides inputs', function () { - this.server.respondWith("POST", "/include", function (xhr) { - - xhr.requestHeaders['i1'].should.equal("best"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make('
    ') - var input = byId("i1") - input.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - -}); \ No newline at end of file diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-history.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-history.js deleted file mode 100644 index cb076ba8fa5..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-history.js +++ /dev/null @@ -1,46 +0,0 @@ -describe("hx-history attribute", function() { - - var HTMX_HISTORY_CACHE_NAME = "htmx-history-cache"; - - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - localStorage.removeItem(HTMX_HISTORY_CACHE_NAME); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - localStorage.removeItem(HTMX_HISTORY_CACHE_NAME); - }); - - it("history cache should not contain embargoed content", function () { - this.server.respondWith("GET", "/test1", '
    test1
    '); - this.server.respondWith("GET", "/test2", '
    test2
    '); - this.server.respondWith("GET", "/test3", '
    test3
    '); - - make('
    init
    '); - - byId("d1").click(); - this.server.respond(); - var workArea = getWorkArea(); - workArea.textContent.should.equal("test1"); - - byId("d2").click(); - this.server.respond(); - workArea.textContent.should.equal("test2"); - - byId("d3").click(); - this.server.respond(); - workArea.textContent.should.equal("test3"); - - // embargoed content should NOT be in the localStorage cache - var cache = JSON.parse(localStorage.getItem(HTMX_HISTORY_CACHE_NAME)); - cache.length.should.equal(2); - - // on history navigation, embargoed content is retrieved from server - htmx._('restoreHistory')("/test2"); - this.server.respond(); - getWorkArea().textContent.should.equal("test2"); - }); - -}); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-include.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-include.js deleted file mode 100644 index 0a7d10525eb..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-include.js +++ /dev/null @@ -1,228 +0,0 @@ -describe("hx-include attribute", function() { - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it('By default an input includes itself', function () { - this.server.respondWith("POST", "/include", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make('
    ') - var input = byId("i1") - input.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('non-GET includes closest form', function () { - this.server.respondWith("POST", "/include", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make('
    ') - var input = byId("d1") - input.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('non-GET includes closest form and overrides values included that exist outside the form', function () { - this.server.respondWith("POST", "/include", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make('
    ' + - '' + - '
    ' + - '') - var input = byId("d1") - input.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('GET does not include closest form by default', function () { - this.server.respondWith("GET", "/include", function (xhr) { - var params = getParameters(xhr); - should.equal(params['i1'], undefined); - xhr.respond(200, {}, "Clicked!") - }); - var div = make('
    ') - var input = byId("d1") - input.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('Single input not included twice when in form', function () { - this.server.respondWith("POST", "/include", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make('
    ') - var input = byId("i1") - input.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('Two inputs are included twice when they have the same name', function () { - this.server.respondWith("POST", "/include", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.deep.equal(["test", "test2"]); - xhr.respond(200, {}, "Clicked!") - }); - var div = make('
    ' + - '' + - '' + - '
    ') - var input = byId("i1") - input.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('Two inputs are included twice when in form when they have the same name', function () { - this.server.respondWith("POST", "/include", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.deep.equal(["test", "test2"]); - xhr.respond(200, {}, "Clicked!") - }); - var div = make('
    ' + - '' + - '' + - '
    ') - var input = byId("i1") - input.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('Input not included twice when it explicitly refers to parent form', function () { - this.server.respondWith("POST", "/include", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make('
    ' + - '' + - '
    ') - var input = byId("i1") - input.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('Input can be referred to externally', function () { - this.server.respondWith("POST", "/include", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - make(''); - var div = make('
    ') - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('Two inputs can be referred to externally', function () { - this.server.respondWith("POST", "/include", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("test"); - params['i2'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - make(''); - make(''); - var div = make('
    ') - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('A form can be referred to externally', function () { - this.server.respondWith("POST", "/include", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("test"); - params['i2'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - make('
    ' + - '' + - '' + - '
    '); - var div = make('
    ') - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('By default an input includes itself w/ data-* prefix', function () { - this.server.respondWith("POST", "/include", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make('
    ') - var input = byId("i1") - input.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('If the element is not includeable, its descendant inputs are included', function () { - this.server.respondWith("POST", "/include", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("test"); - params['i2'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - make('
    '); - var div = make('
    ') - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }) - - it('The `closest` modifier can be used in the hx-include selector', function () { - this.server.respondWith("POST", "/include", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("test"); - params['i2'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - make('
    '+ - '
    '); - var btn = byId('btn') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - }) - - it('The `this` modifier can be used in the hx-include selector', function () { - this.server.respondWith("POST", "/include", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("test"); - params['i2'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - make('
    '+ - '
    '); - var btn = byId('btn') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - }) - -}); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-indicator.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-indicator.js deleted file mode 100644 index 94156f74f3b..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-indicator.js +++ /dev/null @@ -1,137 +0,0 @@ -describe("hx-indicator attribute", function(){ - beforeEach(function() { - this.server = sinon.fakeServer.create(); - clearWorkArea(); - }); - afterEach(function() { - this.server.restore(); - clearWorkArea(); - }); - - it('Indicator classes are properly put on element with no explicit indicator', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - var btn = make('') - btn.click(); - btn.classList.contains("htmx-request").should.equal(true); - this.server.respond(); - btn.classList.contains("htmx-request").should.equal(false); - }); - - it('Indicator classes are properly put on element with explicit indicator', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - var btn = make('') - var a1 = make('') - var a2 = make('') - btn.click(); - btn.classList.contains("htmx-request").should.equal(false); - a1.classList.contains("htmx-request").should.equal(true); - a2.classList.contains("htmx-request").should.equal(true); - this.server.respond(); - btn.classList.contains("htmx-request").should.equal(false); - a1.classList.contains("htmx-request").should.equal(false); - a2.classList.contains("htmx-request").should.equal(false); - }); - - it('Indicator classes are properly put on element with relative indicator', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - var btn = make('') - var a1 = make('') - btn.click(); - btn.classList.contains("htmx-request").should.equal(false); - a1.classList.contains("htmx-request").should.equal(true); - this.server.respond(); - btn.classList.contains("htmx-request").should.equal(false); - a1.classList.contains("htmx-request").should.equal(false); - }); - - it('Indicator classes are properly put on element with explicit indicator w/ data-* prefix', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - var btn = make('') - var a1 = make('') - var a2 = make('') - btn.click(); - btn.classList.contains("htmx-request").should.equal(false); - a1.classList.contains("htmx-request").should.equal(true); - a2.classList.contains("htmx-request").should.equal(true); - this.server.respond(); - btn.classList.contains("htmx-request").should.equal(false); - a1.classList.contains("htmx-request").should.equal(false); - a2.classList.contains("htmx-request").should.equal(false); - }); - - it('allows closest syntax in hx-indicator', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - var div = make('
    ') - var btn = byId("b1"); - btn.click(); - btn.classList.contains("htmx-request").should.equal(false); - div.classList.contains("htmx-request").should.equal(true); - this.server.respond(); - btn.classList.contains("htmx-request").should.equal(false); - div.classList.contains("htmx-request").should.equal(false); - }); - - it('is removed when initiating element is removed from the DOM', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - var indicator = make('
    Indicator
    ') - var div = make('
    ') - var btn = byId("b1"); - btn.click(); - indicator.classList.contains("htmx-request").should.equal(true); - this.server.respond(); - indicator.classList.contains("htmx-request").should.equal(false); - }); - - it('allows this syntax in hx-indicator', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - var div = make('
    ') - var btn = byId("b1"); - btn.click(); - btn.classList.contains("htmx-request").should.equal(false); - div.classList.contains("htmx-request").should.equal(true); - this.server.respond(); - btn.classList.contains("htmx-request").should.equal(false); - div.classList.contains("htmx-request").should.equal(false); - }); - - it('multiple requests with same indicator are handled properly', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - var b1 = make('') - var b2 = make('') - var a1 = make('') - - b1.click(); - b1.classList.contains("htmx-request").should.equal(false); - b2.classList.contains("htmx-request").should.equal(false); - a1.classList.contains("htmx-request").should.equal(true); - - b2.click(); - b1.classList.contains("htmx-request").should.equal(false); - b2.classList.contains("htmx-request").should.equal(false); - a1.classList.contains("htmx-request").should.equal(true); - - // hack to make sinon process only one response - this.server.processRequest(this.server.queue.shift()); - - b1.classList.contains("htmx-request").should.equal(false); - b2.classList.contains("htmx-request").should.equal(false); - a1.classList.contains("htmx-request").should.equal(true); - - this.server.respond(); - - b1.classList.contains("htmx-request").should.equal(false); - b2.classList.contains("htmx-request").should.equal(false); - a1.classList.contains("htmx-request").should.equal(false); - - }); - - -}) diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-on-wildcard.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-on-wildcard.js deleted file mode 100644 index 9aa3633e32b..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-on-wildcard.js +++ /dev/null @@ -1,226 +0,0 @@ -describe("hx-on:* attribute", function() { - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it("can handle basic events w/ no other attributes", function () { - var btn = make(""); - btn.click(); - window.foo.should.equal(true); - delete window.foo; - }); - - it("can use dashes rather than colons", function () { - var btn = make(""); - btn.click(); - window.foo.should.equal(true); - delete window.foo; - }); - - - it("can modify a parameter via htmx:configRequest", function () { - this.server.respondWith("POST", "/test", function (xhr) { - var params = parseParams(xhr.requestBody); - xhr.respond(200, {}, params.foo); - }); - var btn = make(""); - btn.click(); - this.server.respond(); - btn.innerText.should.equal("bar"); - }); - - it("can modify a parameter via htmx:configRequest with dashes", function () { - this.server.respondWith("POST", "/test", function (xhr) { - var params = parseParams(xhr.requestBody); - xhr.respond(200, {}, params.foo); - }); - var btn = make(""); - btn.click(); - this.server.respond(); - btn.innerText.should.equal("bar"); - }); - - it("expands :: shorthand into htmx:", function () { - this.server.respondWith("POST", "/test", function (xhr) { - var params = parseParams(xhr.requestBody); - xhr.respond(200, {}, params.foo); - }); - var btn = make(""); - btn.click(); - this.server.respond(); - btn.innerText.should.equal("bar"); - }); - - it("expands -- shorthand into htmx:", function () { - this.server.respondWith("POST", "/test", function (xhr) { - var params = parseParams(xhr.requestBody); - xhr.respond(200, {}, params.foo); - }); - var btn = make(""); - btn.click(); - this.server.respond(); - btn.innerText.should.equal("bar"); - }); - - it("can cancel an event via preventDefault for htmx:config-request", function () { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, ""); - }); - var btn = make(""); - btn.click(); - this.server.respond(); - btn.innerText.should.equal("Foo"); - }); - - it("can respond to data-hx-on", function () { - this.server.respondWith("POST", "/test", function (xhr) { - var params = parseParams(xhr.requestBody); - xhr.respond(200, {}, params.foo); - }); - var btn = make(""); - btn.click(); - this.server.respond(); - btn.innerText.should.equal("bar"); - }); - - it("has the this symbol set to the element", function () { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, "foo"); - }); - var btn = make(""); - btn.click(); - this.server.respond(); - btn.innerText.should.equal("foo"); - btn.should.equal(window.elt); - delete window.elt; - }); - - it("can handle multi-line JSON", function () { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, "foo"); - }); - var btn = make(""); - btn.click(); - this.server.respond(); - btn.innerText.should.equal("foo"); - var obj = {foo: true, bar: false}; - obj.should.deep.equal(window.elt); - delete window.elt; - }); - - it("can handle multiple event handlers in the presence of multi-line JSON", function () { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, "foo"); - }); - var btn = make(""); - btn.click(); - this.server.respond(); - btn.innerText.should.equal("foo"); - - var obj = {foo: true, bar: false}; - obj.should.deep.equal(window.elt); - delete window.elt; - - window.foo.should.equal(true); - delete window.foo; - }); - - it("de-initializes hx-on-* content properly", function () { - window.tempCount = 0; - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, ""); - }); - var div = make("
    Foo
    "); - - // get response - div.click(); - this.server.respond(); - - // click button - byId('foo').click(); - window.tempCount.should.equal(1); - - // get second response - div.click(); - this.server.respond(); - - // click button again - byId('foo').click(); - window.tempCount.should.equal(2); - - delete window.tempCount; - }); - - it("is not evaluated when allowEval is false", function () { - var calledEvent = false; - var handler = htmx.on("htmx:evalDisallowedError", function(){ - calledEvent = true; - }); - htmx.config.allowEval = false; - try { - var btn = make(""); - btn.click(); - should.not.exist(window.foo); - } finally { - htmx.config.allowEval = true; - htmx.off("htmx:evalDisallowedError", handler); - delete window.foo; - } - calledEvent.should.equal(true); - }); - - it("can handle being swapped using innerHTML", function () { - this.server.respondWith("GET", "/test", function (xhr) { - xhr.respond(200, {}, ''); - }); - - make( - '
    ' - + '' - + '
    ' - + '
    ' - ); - - var fooBtn = byId("foo"); - fooBtn.click(); - window.foo.should.equal(true); - - var swapBtn = byId("swap"); - swapBtn.click(); - this.server.respond(); - - var barBtn = byId("bar"); - barBtn.click(); - window.bar.should.equal(true); - - delete window.foo; - delete window.bar; - }); - - it("cleans up all handlers when the DOM updates", function () { - // setup - window.foo = 0; - window.bar = 0; - var div = make("
    Foo
    "); - make("
    Another Div
    "); // sole purpose is to update the DOM - - // check there is just one handler against each event - htmx.trigger(div, "increment-foo"); - htmx.trigger(div, "increment-bar"); - window.foo.should.equal(1); - window.bar.should.equal(1); - - // teardown - delete window.foo; - delete window.bar; - }); -}); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-on.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-on.js deleted file mode 100644 index 209366b6841..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-on.js +++ /dev/null @@ -1,193 +0,0 @@ -describe("hx-on attribute", function() { - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it("can handle basic events w/ no other attributes", function () { - var btn = make(""); - btn.click(); - window.foo.should.equal(true); - delete window.foo; - }); - - it("can modify a parameter via htmx:configRequest", function () { - this.server.respondWith("POST", "/test", function (xhr) { - var params = parseParams(xhr.requestBody); - xhr.respond(200, {}, params.foo); - }); - var btn = make(""); - btn.click(); - this.server.respond(); - btn.innerText.should.equal("bar"); - }); - - it("can cancel an event via preventDefault for htmx:configRequest", function () { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, ""); - }); - var btn = make(""); - btn.click(); - this.server.respond(); - btn.innerText.should.equal("Foo"); - }); - - it("can respond to kebab-case events", function () { - this.server.respondWith("POST", "/test", function (xhr) { - var params = parseParams(xhr.requestBody); - xhr.respond(200, {}, params.foo); - }); - var btn = make(""); - btn.click(); - this.server.respond(); - btn.innerText.should.equal("bar"); - }); - - it("has the this symbol set to the element", function () { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, "foo"); - }); - var btn = make(""); - btn.click(); - this.server.respond(); - btn.innerText.should.equal("foo"); - btn.should.equal(window.elt); - delete window.elt; - }); - - it("can handle multi-line JSON", function () { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, "foo"); - }); - var btn = make(""); - btn.click(); - this.server.respond(); - btn.innerText.should.equal("foo"); - var obj = {foo: true, bar: false}; - obj.should.deep.equal(window.elt); - delete window.elt; - }); - - it("can handle multiple event handlers in the presence of multi-line JSON", function () { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, "foo"); - }); - var btn = make(""); - btn.click(); - this.server.respond(); - btn.innerText.should.equal("foo"); - - var obj = {foo: true, bar: false}; - obj.should.deep.equal(window.elt); - delete window.elt; - - window.foo.should.equal(true); - delete window.foo; - }); - - it("de-initializes hx-on content properly", function () { - window.tempCount = 0; - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, ""); - }); - var div = make("
    Foo
    "); - - // get response - div.click(); - this.server.respond(); - - // click button - byId('foo').click(); - window.tempCount.should.equal(1); - - // get second response - div.click(); - this.server.respond(); - - // click button again - byId('foo').click(); - window.tempCount.should.equal(2); - - delete window.tempCount; - }); - - it("is not evaluated when allowEval is false", function () { - var calledEvent = false; - var handler = htmx.on("htmx:evalDisallowedError", function(){ - calledEvent = true; - }); - htmx.config.allowEval = false; - try { - var btn = make(""); - btn.click(); - should.not.exist(window.foo); - } finally { - htmx.config.allowEval = true; - htmx.off("htmx:evalDisallowedError", handler); - delete window.foo; - } - calledEvent.should.equal(true); - }); - - it("can handle event types with dots", function () { - var btn = make(""); - // IE11 doesn't support `new CustomEvent()` so call htmx' internal utility function - btn.dispatchEvent(htmx._("makeEvent")('my.custom.event')); - window.foo.should.equal(true); - delete window.foo; - }); - - it("can handle being swapped using innerHTML", function () { - this.server.respondWith("GET", "/test", function (xhr) { - xhr.respond(200, {}, ''); - }); - - make( - '
    ' - + '' - + '
    ' - + '
    ' - ); - - var fooBtn = byId("foo"); - fooBtn.click(); - window.foo.should.equal(true); - - var swapBtn = byId("swap"); - swapBtn.click(); - this.server.respond(); - - var barBtn = byId("bar"); - barBtn.click(); - window.bar.should.equal(true); - - delete window.foo; - delete window.bar; - }); - - it("cleans up all handlers when the DOM updates", function () { - // setup - window.foo = 0; - window.bar = 0; - var div = make("
    Foo
    "); - make("
    Another Div
    "); // sole purpose is to update the DOM - - // check there is just one handler against each event - htmx.trigger(div, "increment-foo"); - htmx.trigger(div, "increment-bar"); - window.foo.should.equal(1); - window.bar.should.equal(1); - - // teardown - delete window.foo; - delete window.bar; - }); -}); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-params.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-params.js deleted file mode 100644 index b2b19ca2556..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-params.js +++ /dev/null @@ -1,101 +0,0 @@ -describe("hx-params attribute", function() { - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it('none excludes all params', function () { - this.server.respondWith("POST", "/params", function (xhr) { - var params = getParameters(xhr); - should.equal(params['i1'], undefined); - should.equal(params['i2'], undefined); - should.equal(params['i3'], undefined); - xhr.respond(200, {}, "Clicked!") - }); - var form = make('
    ' + - '' + - '' + - '' + - '
    '); - form.click(); - this.server.respond(); - form.innerHTML.should.equal("Clicked!"); - }); - - it('"*" includes all params', function () { - this.server.respondWith("POST", "/params", function (xhr) { - var params = getParameters(xhr); - should.equal(params['i1'], "test"); - should.equal(params['i2'], "test"); - should.equal(params['i3'], "test"); - xhr.respond(200, {}, "Clicked!") - }); - var form = make('
    ' + - '' + - '' + - '' + - '
    '); - form.click(); - this.server.respond(); - form.innerHTML.should.equal("Clicked!"); - }); - - it('named includes works', function () { - this.server.respondWith("POST", "/params", function (xhr) { - var params = getParameters(xhr); - should.equal(params['i1'], "test"); - should.equal(params['i2'], undefined); - should.equal(params['i3'], "test"); - xhr.respond(200, {}, "Clicked!") - }); - var form = make('
    ' + - '' + - '' + - '' + - '
    '); - form.click(); - this.server.respond(); - form.innerHTML.should.equal("Clicked!"); - }); - - it('named exclude works', function () { - this.server.respondWith("POST", "/params", function (xhr) { - var params = getParameters(xhr); - should.equal(params['i1'], undefined); - should.equal(params['i2'], "test"); - should.equal(params['i3'], undefined); - xhr.respond(200, {}, "Clicked!") - }); - var form = make('
    ' + - '' + - '' + - '' + - '
    '); - form.click(); - this.server.respond(); - form.innerHTML.should.equal("Clicked!"); - }); - - it('named exclude works w/ data-* prefix', function () { - this.server.respondWith("POST", "/params", function (xhr) { - var params = getParameters(xhr); - should.equal(params['i1'], undefined); - should.equal(params['i2'], "test"); - should.equal(params['i3'], undefined); - xhr.respond(200, {}, "Clicked!") - }); - var form = make('
    ' + - '' + - '' + - '' + - '
    '); - form.click(); - this.server.respond(); - form.innerHTML.should.equal("Clicked!"); - }); - -}); \ No newline at end of file diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-patch.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-patch.js deleted file mode 100644 index a3c5198478d..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-patch.js +++ /dev/null @@ -1,34 +0,0 @@ -describe("hx-patch attribute", function(){ - beforeEach(function() { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function() { - this.server.restore(); - clearWorkArea(); - }); - - it('issues a PATCH request', function() - { - this.server.respondWith("PATCH", "/test", function(xhr){ - xhr.respond(200, {}, "Patched!"); - }); - - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Patched!"); - }); - - it('issues a PATCH request w/ data-* prefix', function() - { - this.server.respondWith("PATCH", "/test", function(xhr){ - xhr.respond(200, {}, "Patched!"); - }); - - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Patched!"); - }); -}) diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-post.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-post.js deleted file mode 100644 index 6734e30d21e..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-post.js +++ /dev/null @@ -1,36 +0,0 @@ -describe("hx-post attribute", function(){ - beforeEach(function() { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function() { - this.server.restore(); - clearWorkArea(); - }); - - it('issues a POST request with proper headers', function() - { - this.server.respondWith("POST", "/test", function(xhr){ - should.equal(xhr.requestHeaders['X-HTTP-Method-Override'], undefined); - xhr.respond(200, {}, "Posted!"); - }); - - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Posted!"); - }); - - it('issues a POST request with proper headers w/ data-* prefix', function() - { - this.server.respondWith("POST", "/test", function(xhr){ - should.equal(xhr.requestHeaders['X-HTTP-Method-Override'], undefined); - xhr.respond(200, {}, "Posted!"); - }); - - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Posted!"); - }); -}) diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-preserve.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-preserve.js deleted file mode 100644 index 1e1c2368a45..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-preserve.js +++ /dev/null @@ -1,39 +0,0 @@ -describe("hx-preserve attribute", function () { - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it('handles basic response properly', function () { - this.server.respondWith("GET", "/test", "
    New Content
    New Content
    "); - var div = make("
    Old Content
    Old Content
    "); - div.click(); - this.server.respond(); - byId("d1").innerHTML.should.equal("Old Content"); - byId("d2").innerHTML.should.equal("New Content"); - }) - - it('handles preserved element that might not be existing', function () { - this.server.respondWith("GET", "/test", "
    New Content
    New Content
    "); - var div = make("
    Old Content
    "); - div.click(); - this.server.respond(); - byId("d1").innerHTML.should.equal("New Content"); - byId("d2").innerHTML.should.equal("New Content"); - }) - - it('preserved element should not be swapped if it lies outside of hx-select', function () { - this.server.respondWith("GET", "/test", "
    New Content
    New Content
    "); - var div = make("
    Old Content
    Old Content
    "); - div.click(); - this.server.respond(); - byId("d1").innerHTML.should.equal("Old Content"); - byId("d2").innerHTML.should.equal("New Content"); - }) - -}); - diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-push-url.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-push-url.js deleted file mode 100644 index 50b88d8061d..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-push-url.js +++ /dev/null @@ -1,223 +0,0 @@ -describe("hx-push-url attribute", function() { - - var HTMX_HISTORY_CACHE_NAME = "htmx-history-cache"; - - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - localStorage.removeItem(HTMX_HISTORY_CACHE_NAME); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - localStorage.removeItem(HTMX_HISTORY_CACHE_NAME); - }); - - it("navigation should push an element into the cache when true", function () { - this.server.respondWith("GET", "/test", "second"); - getWorkArea().innerHTML.should.be.equal(""); - var div = make('
    first
    '); - div.click(); - this.server.respond(); - div.click(); - this.server.respond(); - getWorkArea().textContent.should.equal("second") - var cache = JSON.parse(localStorage.getItem(HTMX_HISTORY_CACHE_NAME)); - console.log(cache); - cache[cache.length - 1].url.should.equal("/test"); - }); - - it("navigation should push an element into the cache when string", function () { - this.server.respondWith("GET", "/test", "second"); - getWorkArea().innerHTML.should.be.equal(""); - var div = make('
    first
    '); - div.click(); - this.server.respond(); - div.click(); - this.server.respond(); - getWorkArea().textContent.should.equal("second") - var cache = JSON.parse(localStorage.getItem(HTMX_HISTORY_CACHE_NAME)); - cache.length.should.equal(2); - cache[1].url.should.equal("/abc123"); - }); - - it("restore should return old value", function () { - this.server.respondWith("GET", "/test1", '
    test1
    '); - this.server.respondWith("GET", "/test2", '
    test2
    '); - - make('
    init
    '); - - byId("d1").click(); - this.server.respond(); - var workArea = getWorkArea(); - workArea.textContent.should.equal("test1") - - byId("d2").click(); - this.server.respond(); - workArea.textContent.should.equal("test2") - - var cache = JSON.parse(localStorage.getItem(HTMX_HISTORY_CACHE_NAME)); - - cache.length.should.equal(2); - htmx._('restoreHistory')("/test1") - getWorkArea().textContent.should.equal("test1") - }); - - it("history restore should not have htmx support classes in content", function () { - this.server.respondWith("GET", "/test1", '
    test1
    '); - this.server.respondWith("GET", "/test2", '
    test2
    '); - - make('
    init
    '); - - byId("d1").click(); - this.server.respond(); - var workArea = getWorkArea(); - workArea.textContent.should.equal("test1") - - byId("d2").click(); - this.server.respond(); - workArea.textContent.should.equal("test2") - - htmx._('restoreHistory')("/test1") - getWorkArea().getElementsByClassName("htmx-request").length.should.equal(0); - }); - - it("cache should only store 10 entries", function () { - var x = 0; - this.server.respondWith("GET", /test.*/, function(xhr){ - x++; - xhr.respond(200, {}, '
    ') - }); - getWorkArea().innerHTML.should.be.equal(""); - make('
    '); - for (var i = 0; i < 20; i++) { // issue 20 requests - byId("d1").click(); - this.server.respond(); - } - var cache = JSON.parse(localStorage.getItem(HTMX_HISTORY_CACHE_NAME)); - cache.length.should.equal(10); // should only be 10 elements - }); - - it("cache miss should issue another GET", function () { - this.server.respondWith("GET", "/test1", '
    test1
    '); - this.server.respondWith("GET", "/test2", '
    test2
    '); - - make('
    init
    '); - - byId("d1").click(); - this.server.respond(); - var workArea = getWorkArea(); - workArea.textContent.should.equal("test1") - - byId("d2").click(); - this.server.respond(); - workArea.textContent.should.equal("test2") - - var cache = JSON.parse(localStorage.getItem(HTMX_HISTORY_CACHE_NAME)); - - cache.length.should.equal(2); - localStorage.removeItem(HTMX_HISTORY_CACHE_NAME); // clear cache - htmx._('restoreHistory')("/test1") - this.server.respond(); - getWorkArea().textContent.should.equal("test1") - }); - - it("navigation should push an element into the cache w/ data-* prefix", function () { - this.server.respondWith("GET", "/test", "second"); - getWorkArea().innerHTML.should.be.equal(""); - var div = make('
    first
    '); - div.click(); - this.server.respond(); - getWorkArea().textContent.should.equal("second") - var cache = JSON.parse(localStorage.getItem(HTMX_HISTORY_CACHE_NAME)); - cache.length.should.equal(1); - }); - - it("deals with malformed JSON in history cache when getting", function () { - localStorage.setItem(HTMX_HISTORY_CACHE_NAME, "Invalid JSON"); - var history = htmx._('getCachedHistory')('url'); - should.equal(history, null); - }); - - it("deals with malformed JSON in history cache when saving", function () { - localStorage.setItem(HTMX_HISTORY_CACHE_NAME, "Invalid JSON"); - htmx._('saveToHistoryCache')('url', 'content', 'title', 'scroll'); - var cache = JSON.parse(localStorage.getItem(HTMX_HISTORY_CACHE_NAME)); - cache.length.should.equal(1); - }); - - it("does not blow out cache when saving a URL twice", function () { - htmx._('saveToHistoryCache')('url1', 'content', 'title', 'scroll'); - htmx._('saveToHistoryCache')('url2', 'content', 'title', 'scroll'); - htmx._('saveToHistoryCache')('url3', 'content', 'title', 'scroll'); - htmx._('saveToHistoryCache')('url2', 'content', 'title', 'scroll'); - var cache = JSON.parse(localStorage.getItem(HTMX_HISTORY_CACHE_NAME)); - cache.length.should.equal(3); - }); - - it("history cache is LRU", function () { - htmx._('saveToHistoryCache')('url1', 'content', 'title', 'scroll'); - htmx._('saveToHistoryCache')('url2', 'content', 'title', 'scroll'); - htmx._('saveToHistoryCache')('url3', 'content', 'title', 'scroll'); - htmx._('saveToHistoryCache')('url2', 'content', 'title', 'scroll'); - htmx._('saveToHistoryCache')('url1', 'content', 'title', 'scroll'); - var cache = JSON.parse(localStorage.getItem(HTMX_HISTORY_CACHE_NAME)); - cache.length.should.equal(3); - cache[0].url.should.equal("url3"); - cache[1].url.should.equal("url2"); - cache[2].url.should.equal("url1"); - }); - - it("htmx:afterSettle is called when replacing outerHTML", function () { - var called = false; - var handler = htmx.on("htmx:afterSettle", function (evt) { - called = true; - }); - try { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, ""); - }); - var div = make(""); - div.click(); - this.server.respond(); - should.equal(called, true); - } finally { - htmx.off("htmx:afterSettle", handler); - } - }); - - it("should include parameters on a get", function () { - var path = ""; - var handler = htmx.on("htmx:pushedIntoHistory", function (evt) { - path = evt.detail.path; - }); - try { - this.server.respondWith("GET", /test.*/, function (xhr) { - xhr.respond(200, {}, "second") - }); - var form = make('
    first
    '); - form.click(); - this.server.respond(); - form.textContent.should.equal("second") - path.should.equal("/test?foo=bar") - } finally { - htmx.off("htmx:pushedIntoHistory", handler); - } - }); - - it("saveToHistoryCache should not throw", function () { - var bigContent = "Dummy"; - for (var i = 0; i < 20; i++) { - bigContent += bigContent; - } - try { - localStorage.removeItem("htmx-history-cache"); - htmx._("saveToHistoryCache")("/dummy", bigContent, "Foo", 0); - should.equal(localStorage.getItem("htmx-history-cache"), null); - } finally { - // clear history cache afterwards - localStorage.removeItem("htmx-history-cache"); - } - }); - -}); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-put.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-put.js deleted file mode 100644 index 589ec199d05..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-put.js +++ /dev/null @@ -1,34 +0,0 @@ -describe("hx-put attribute", function(){ - beforeEach(function() { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function() { - this.server.restore(); - clearWorkArea(); - }); - - it('issues a PUT request', function() - { - this.server.respondWith("PUT", "/test", function(xhr){ - xhr.respond(200, {}, "Putted!"); - }); - - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Putted!"); - }); - - it('issues a PUT request w/ data-* prefix', function() - { - this.server.respondWith("PUT", "/test", function(xhr){ - xhr.respond(200, {}, "Putted!"); - }); - - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Putted!"); - }); -}) diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-request.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-request.js deleted file mode 100644 index e64f6481f00..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-request.js +++ /dev/null @@ -1,39 +0,0 @@ -describe("hx-request attribute", function() { - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it('basic hx-request timeout works', function (done) { - var timedOut = false; - this.server.respondWith("GET", "/test", "Clicked!"); - var div = make("
    ") - htmx.on(div, 'htmx:timeout', function(){ - timedOut = true; - }) - div.click(); - setTimeout(function(){ - div.innerHTML.should.equal(""); - // unfortunately it looks like sinon.js doesn't implement the timeout functionality - // timedOut.should.equal(true); - done(); - }, 400) - }); - - it('hx-request header works', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - should.equal(xhr.requestHeaders['HX-Request'], undefined); - xhr.respond(200, {}, "Clicked!") - }); - var div = make("
    ") - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - -}); \ No newline at end of file diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-select-oob.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-select-oob.js deleted file mode 100644 index 570811e8574..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-select-oob.js +++ /dev/null @@ -1,54 +0,0 @@ -describe("hx-select-oob attribute", function () { - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it('basic hx-select-oob works', function() - { - this.server.respondWith("GET", "/test", "
    foo
    bar
    "); - var div = make('
    '); - make('
    '); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("
    foo
    "); - var div2 = byId('d2'); - div2.innerHTML.should.equal("bar"); - }); - - it('multiple hx-select-oobs works', function() - { - this.server.respondWith("GET", "/test", "
    foo
    bar
    bar
    "); - var div = make('
    '); - make('
    '); - make('
    '); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("
    foo
    "); - - var div2 = byId('d2'); - div2.innerHTML.should.equal("bar"); - - var div3 = byId('d2'); - div3.innerHTML.should.equal("bar"); - }); - - it('basic hx-select-oob ignores bad selector', function() - { - this.server.respondWith("GET", "/test", "
    foo
    bar
    "); - var div = make('
    '); - make('
    '); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("
    foo
    "); - var div2 = byId('d2'); - div2.innerHTML.should.equal(""); - }); - - -}); - diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-select.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-select.js deleted file mode 100644 index c5868430870..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-select.js +++ /dev/null @@ -1,40 +0,0 @@ -describe("BOOTSTRAP - htmx AJAX Tests", function(){ - beforeEach(function() { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function() { - this.server.restore(); - clearWorkArea(); - }); - - it('properly handles a partial of HTML', function() - { - var i = 1; - this.server.respondWith("GET", "/test", "
    foo
    bar
    "); - var div = make('
    '); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("
    foo
    "); - }); - - it('properly handles a full HTML document', function() - { - var i = 1; - this.server.respondWith("GET", "/test", "
    foo
    bar
    "); - var div = make('
    '); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("
    foo
    "); - }); - - it('properly handles a full HTML document w/ data-* prefix', function() - { - var i = 1; - this.server.respondWith("GET", "/test", "
    foo
    bar
    "); - var div = make('
    '); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("
    foo
    "); - }); -}) diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-sse.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-sse.js deleted file mode 100644 index 81cb0d04343..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-sse.js +++ /dev/null @@ -1,161 +0,0 @@ -describe("hx-sse attribute", function() { - - function mockEventSource() { - var listeners = {}; - var wasClosed = false; - var mockEventSource = { - removeEventListener: function(name, l) { - listeners[name] = listeners[name].filter(function(elt, idx, arr) { - if (arr[idx] === l) { - return false; - } - return true; - }) - }, - addEventListener: function(message, l) { - if (listeners[message] === undefined) { - listeners[message] = []; - } - listeners[message].push(l) - }, - sendEvent: function(eventName, data) { - var eventListeners = listeners[eventName]; - if (eventListeners) { - eventListeners.forEach(function(listener) { - var event = htmx._("makeEvent")(eventName); - event.data = data; - listener(event); - }) - } - }, - close: function() { - wasClosed = true; - }, - wasClosed: function() { - return wasClosed; - } - }; - return mockEventSource; - } - - beforeEach(function() { - this.server = makeServer(); - var eventSource = mockEventSource(); - this.eventSource = eventSource; - clearWorkArea(); - htmx.createEventSource = function() { return eventSource }; - }); - afterEach(function() { - this.server.restore(); - this.eventSource = mockEventSource(); - clearWorkArea(); - }); - - it('handles basic sse triggering', function() { - - this.server.respondWith("GET", "/d1", "div1 updated"); - this.server.respondWith("GET", "/d2", "div2 updated"); - - var div = make('
    ' + - '
    div1
    ' + - '
    div2
    ' + - '
    '); - - this.eventSource.sendEvent("e1"); - this.server.respond(); - byId("d1").innerHTML.should.equal("div1 updated"); - byId("d2").innerHTML.should.equal("div2"); - - this.eventSource.sendEvent("e2"); - this.server.respond(); - byId("d1").innerHTML.should.equal("div1 updated"); - byId("d2").innerHTML.should.equal("div2 updated"); - }) - - it('does not trigger events that arent named', function() { - - this.server.respondWith("GET", "/d1", "div1 updated"); - - var div = make('
    ' + - '
    div1
    ' + - '
    '); - - this.eventSource.sendEvent("foo"); - this.server.respond(); - byId("d1").innerHTML.should.equal("div1"); - - this.eventSource.sendEvent("e2"); - this.server.respond(); - byId("d1").innerHTML.should.equal("div1"); - - this.eventSource.sendEvent("e1"); - this.server.respond(); - byId("d1").innerHTML.should.equal("div1 updated"); - }) - - it('does not trigger events not on descendents', function() { - - this.server.respondWith("GET", "/d1", "div1 updated"); - - var div = make('
    ' + - '
    div1
    '); - - this.eventSource.sendEvent("foo"); - this.server.respond(); - byId("d1").innerHTML.should.equal("div1"); - - this.eventSource.sendEvent("e2"); - this.server.respond(); - byId("d1").innerHTML.should.equal("div1"); - - this.eventSource.sendEvent("e1"); - this.server.respond(); - byId("d1").innerHTML.should.equal("div1"); - }) - - it('is closed after removal', function() { - this.server.respondWith("GET", "/test", "Clicked!"); - var div = make('
    ' + - '
    div1
    ' + - '
    '); - div.click(); - this.server.respond(); - this.eventSource.wasClosed().should.equal(true) - }) - - it('is closed after removal with no close and activity', function() { - var div = make('
    ' + - '
    div1
    ' + - '
    '); - div.parentElement.removeChild(div); - this.eventSource.sendEvent("e1") - this.eventSource.wasClosed().should.equal(true) - }) - - it('swaps content properly on SSE swap', function() { - var div = make('
    \n' + - '
    \n' + - '
    \n' + - '
    \n'); - byId("d1").innerText.should.equal("") - byId("d2").innerText.should.equal("") - this.eventSource.sendEvent("e1", "Event 1") - byId("d1").innerText.should.equal("Event 1") - byId("d2").innerText.should.equal("") - this.eventSource.sendEvent("e2", "Event 2") - byId("d1").innerText.should.equal("Event 1") - byId("d2").innerText.should.equal("Event 2") - }) - - it('swaps swapped in content', function() { - var div = make('
    \n' + - '
    \n' + - '
    \n' - ) - - this.eventSource.sendEvent("e1", '
    ') - this.eventSource.sendEvent("e2", 'Event 2') - byId("d2").innerText.should.equal("Event 2") - }) -}); - diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-swap-oob.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-swap-oob.js deleted file mode 100644 index e69c43e682b..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-swap-oob.js +++ /dev/null @@ -1,132 +0,0 @@ -describe("hx-swap-oob attribute", function () { - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it('handles basic response properly', function () { - this.server.respondWith("GET", "/test", "Clicked
    Swapped0
    "); - var div = make('
    click me
    '); - make('
    '); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked"); - byId("d1").innerHTML.should.equal("Swapped0"); - }) - - it('handles more than one oob swap properly', function () { - this.server.respondWith("GET", "/test", "Clicked
    Swapped1
    Swapped2
    "); - var div = make('
    click me
    '); - make('
    '); - make('
    '); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked"); - byId("d1").innerHTML.should.equal("Swapped1"); - byId("d2").innerHTML.should.equal("Swapped2"); - }) - - it('handles no id match properly', function () { - this.server.respondWith("GET", "/test", "Clicked
    Swapped2
    "); - var div = make('
    click me
    '); - div.click(); - this.server.respond(); - div.innerText.should.equal("Clicked"); - }) - - it('handles basic response properly w/ data-* prefix', function () { - this.server.respondWith("GET", "/test", "Clicked
    Swapped3
    "); - var div = make('
    click me
    '); - make('
    '); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked"); - byId("d1").innerHTML.should.equal("Swapped3"); - }) - - it('handles outerHTML response properly', function () { - this.server.respondWith("GET", "/test", "Clicked
    Swapped4
    "); - var div = make('
    click me
    '); - make('
    '); - div.click(); - this.server.respond(); - byId("d1").getAttribute("foo").should.equal("bar"); - div.innerHTML.should.equal("Clicked"); - byId("d1").innerHTML.should.equal("Swapped4"); - }) - - it('handles innerHTML response properly', function () { - this.server.respondWith("GET", "/test", "Clicked
    Swapped5
    "); - var div = make('
    click me
    '); - make('
    '); - div.click(); - this.server.respond(); - should.equal(byId("d1").getAttribute("foo"), null); - div.innerHTML.should.equal("Clicked"); - byId("d1").innerHTML.should.equal("Swapped5"); - }) - - it('oob swaps can be nested in content', function () { - this.server.respondWith("GET", "/test", "
    Clicked
    Swapped6
    "); - var div = make('
    click me
    '); - make('
    '); - div.click(); - this.server.respond(); - should.equal(byId("d1").getAttribute("foo"), null); - div.innerHTML.should.equal("
    Clicked
    "); - byId("d1").innerHTML.should.equal("Swapped6"); - }) - - it('oob swaps can use selectors to match up', function () { - this.server.respondWith("GET", "/test", "
    Clicked
    Swapped7
    "); - var div = make('
    click me
    '); - make('
    '); - div.click(); - this.server.respond(); - should.equal(byId("d1").getAttribute("oob-foo"), "bar"); - div.innerHTML.should.equal("
    Clicked
    "); - byId("d1").innerHTML.should.equal("Swapped7"); - }) - - it('swaps into all targets that match the selector (innerHTML)', function () { - this.server.respondWith("GET", "/test", "
    Clicked
    Swapped8
    "); - var div = make('
    click me
    '); - make('
    No swap
    '); - make('
    Not swapped
    '); - make('
    Not swapped
    '); - div.click(); - this.server.respond(); - byId("d1").innerHTML.should.equal("No swap"); - byId("d2").innerHTML.should.equal("Swapped8"); - byId("d3").innerHTML.should.equal("Swapped8"); - }) - - it('swaps into all targets that match the selector (outerHTML)', function () { - var oobSwapContent = '
    Swapped9
    '; - this.server.respondWith("GET", "/test", "
    Clicked
    " + oobSwapContent); - var div = make('
    click me
    '); - make('
    No swap
    '); - make('
    Not swapped
    '); - make('
    Not swapped
    '); - div.click(); - this.server.respond(); - byId("d1").innerHTML.should.equal("
    No swap
    "); - byId("d2").innerHTML.should.equal(oobSwapContent); - byId("d3").innerHTML.should.equal(oobSwapContent); - }) - - it('oob swap delete works properly', function() - { - this.server.respondWith("GET", "/test", '
    '); - - var div = make('
    Foo
    ') - div.click(); - this.server.respond(); - should.equal(byId("d1"), null); - }); -}); - diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-swap.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-swap.js deleted file mode 100644 index 4ff63621fe3..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-swap.js +++ /dev/null @@ -1,374 +0,0 @@ -describe("hx-swap attribute", function(){ - beforeEach(function() { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function() { - this.server.restore(); - clearWorkArea(); - }); - - it('swap innerHTML properly', function() - { - this.server.respondWith("GET", "/test", 'Click Me'); - this.server.respondWith("GET", "/test2", "Clicked!"); - - var div = make('
    ') - div.click(); - this.server.respond(); - div.innerHTML.should.equal('Click Me'); - var a = div.querySelector('a'); - a.click(); - this.server.respond(); - a.innerHTML.should.equal('Clicked!'); - }); - - it('swap outerHTML properly', function() - { - this.server.respondWith("GET", "/test", 'Click Me'); - this.server.respondWith("GET", "/test2", "Clicked!"); - - var div = make('
    ') - div.click(); - should.equal(byId("d1"), div); - this.server.respond(); - should.equal(byId("d1"), null); - byId("a1").click(); - this.server.respond(); - byId("a1").innerHTML.should.equal('Clicked!'); - }); - - it('swap beforebegin properly', function() - { - var i = 0; - this.server.respondWith("GET", "/test", function(xhr){ - i++; - xhr.respond(200, {}, '' + i + ''); - }); - this.server.respondWith("GET", "/test2", "*"); - - var div = make('
    *
    ') - var parent = div.parentElement; - div.click(); - this.server.respond(); - div.innerText.should.equal("*"); - removeWhiteSpace(parent.innerText).should.equal("1*"); - - byId("a1").click(); - this.server.respond(); - removeWhiteSpace(parent.innerText).should.equal("**"); - - div.click(); - this.server.respond(); - div.innerText.should.equal("*"); - removeWhiteSpace(parent.innerText).should.equal("*2*"); - - byId("a2").click(); - this.server.respond(); - removeWhiteSpace(parent.innerText).should.equal("***"); - }); - - it('swap afterbegin properly', function() - { - var i = 0; - this.server.respondWith("GET", "/test", function(xhr){ - i++; - xhr.respond(200, {}, "" + i); - }); - - var div = make('
    *
    ') - - div.click(); - this.server.respond(); - div.innerText.should.equal("1*"); - - div.click(); - this.server.respond(); - div.innerText.should.equal("21*"); - - div.click(); - this.server.respond(); - div.innerText.should.equal("321*"); - }); - - it('swap afterbegin properly with no initial content', function() - { - var i = 0; - this.server.respondWith("GET", "/test", function(xhr){ - i++; - xhr.respond(200, {}, "" + i); - }); - - var div = make('
    ') - - div.click(); - this.server.respond(); - div.innerText.should.equal("1"); - - div.click(); - this.server.respond(); - div.innerText.should.equal("21"); - - div.click(); - this.server.respond(); - div.innerText.should.equal("321"); - }); - - it('swap afterend properly', function() - { - var i = 0; - this.server.respondWith("GET", "/test", function(xhr){ - i++; - xhr.respond(200, {}, '' + i + ''); - }); - this.server.respondWith("GET", "/test2", "*"); - - var div = make('
    *
    ') - var parent = div.parentElement; - div.click(); - this.server.respond(); - div.innerText.should.equal("*"); - removeWhiteSpace(parent.innerText).should.equal("*1"); - - byId("a1").click(); - this.server.respond(); - removeWhiteSpace(parent.innerText).should.equal("**"); - - div.click(); - this.server.respond(); - div.innerText.should.equal("*"); - removeWhiteSpace(parent.innerText).should.equal("*2*"); - - byId("a2").click(); - this.server.respond(); - removeWhiteSpace(parent.innerText).should.equal("***"); - }); - - it('handles beforeend properly', function() - { - var i = 0; - this.server.respondWith("GET", "/test", function(xhr){ - i++; - xhr.respond(200, {}, "" + i); - }); - - var div = make('
    *
    ') - - div.click(); - this.server.respond(); - div.innerText.should.equal("*1"); - - div.click(); - this.server.respond(); - div.innerText.should.equal("*12"); - - div.click(); - this.server.respond(); - div.innerText.should.equal("*123"); - }); - - it('handles beforeend properly with no initial content', function() - { - var i = 0; - this.server.respondWith("GET", "/test", function(xhr){ - i++; - xhr.respond(200, {}, "" + i); - }); - - var div = make('
    ') - - div.click(); - this.server.respond(); - div.innerText.should.equal("1"); - - div.click(); - this.server.respond(); - div.innerText.should.equal("12"); - - div.click(); - this.server.respond(); - div.innerText.should.equal("123"); - }); - - it('properly parses various swap specifications', function(){ - var swapSpec = htmx._("getSwapSpecification"); // internal function for swap spec - swapSpec(make("
    ")).swapStyle.should.equal("innerHTML") - swapSpec(make("
    ")).swapStyle.should.equal("innerHTML") - swapSpec(make("
    ")).swapDelay.should.equal(0) - swapSpec(make("
    ")).settleDelay.should.equal(0) // set to 0 in tests - swapSpec(make("
    ")).swapDelay.should.equal(10) - swapSpec(make("
    ")).swapDelay.should.equal(0) - swapSpec(make("
    ")).swapDelay.should.equal(0) - swapSpec(make("
    ")).settleDelay.should.equal(10) - swapSpec(make("
    ")).settleDelay.should.equal(0) - swapSpec(make("
    ")).settleDelay.should.equal(0) - swapSpec(make("
    ")).swapDelay.should.equal(10) - swapSpec(make("
    ")).settleDelay.should.equal(11) - swapSpec(make("
    ")).swapDelay.should.equal(10) - swapSpec(make("
    ")).settleDelay.should.equal(11) - swapSpec(make("
    ")).settleDelay.should.equal(0) - swapSpec(make("
    ")).settleDelay.should.equal(0) - swapSpec(make("
    ")).settleDelay.should.equal(0) - swapSpec(make("
    ")).settleDelay.should.equal(0) - swapSpec(make("
    ")).settleDelay.should.equal(11) - swapSpec(make("
    ")).settleDelay.should.equal(11) - - swapSpec(make("
    ")).swapStyle.should.equal("innerHTML") - swapSpec(make("
    ")).swapDelay.should.equal(10) - swapSpec(make("
    ")).swapDelay.should.equal(0); - swapSpec(make("
    ")).swapDelay.should.equal(0); - - swapSpec(make("
    ")).swapStyle.should.equal("innerHTML") - swapSpec(make("
    ")).settleDelay.should.equal(10) - swapSpec(make("
    ")).settleDelay.should.equal(0) - swapSpec(make("
    ")).settleDelay.should.equal(0) - - swapSpec(make("
    ")).swapStyle.should.equal("innerHTML") - swapSpec(make("
    ")).swapDelay.should.equal(10) - swapSpec(make("
    ")).settleDelay.should.equal(11) - swapSpec(make("
    ")).swapDelay.should.equal(0) - swapSpec(make("
    ")).settleDelay.should.equal(0) - - swapSpec(make("
    ")).swapStyle.should.equal("innerHTML") - swapSpec(make("
    ")).swapDelay.should.equal(10) - swapSpec(make("
    ")).settleDelay.should.equal(11) - swapSpec(make("
    ")).swapDelay.should.equal(10) - swapSpec(make("
    ")).settleDelay.should.equal(0) - - swapSpec(make("
    ")).swapStyle.should.equal("customstyle") - }) - - it('works with a swap delay', function(done) { - this.server.respondWith("GET", "/test", "Clicked!"); - var div = make("
    "); - div.click(); - this.server.respond(); - div.innerText.should.equal(""); - setTimeout(function () { - div.innerText.should.equal("Clicked!"); - done(); - }, 30); - }); - - it("works immediately with no swap delay", function (done) { - this.server.respondWith("GET", "/test", "Clicked!"); - var div = make( - "
    " - ); - div.click(); - this.server.respond(); - div.innerText.should.equal("Clicked!"); - done(); - }); - - it('works with a settle delay', function(done) { - this.server.respondWith("GET", "/test", "
    "); - var div = make("
    "); - div.click(); - this.server.respond(); - div.classList.contains('foo').should.equal(false); - setTimeout(function () { - byId('d1').classList.contains('foo').should.equal(true); - done(); - }, 30); - }); - - it("works with no settle delay", function (done) { - this.server.respondWith( - "GET", - "/test", - "
    " - ); - var div = make( - "
    " - ); - div.click(); - this.server.respond(); - div.classList.contains("foo").should.equal(false); - setTimeout(function () { - byId("d1").classList.contains("foo").should.equal(true); - done(); - }, 30); - }); - - it('swap outerHTML properly w/ data-* prefix', function() - { - this.server.respondWith("GET", "/test", 'Click Me'); - this.server.respondWith("GET", "/test2", "Clicked!"); - - var div = make('
    ') - div.click(); - should.equal(byId("d1"), div); - this.server.respond(); - should.equal(byId("d1"), null); - byId("a1").click(); - this.server.respond(); - byId("a1").innerHTML.should.equal('Clicked!'); - }); - - it('swap none works properly', function() - { - this.server.respondWith("GET", "/test", 'Ooops, swapped'); - - var div = make('
    Foo
    ') - div.click(); - this.server.respond(); - div.innerHTML.should.equal('Foo'); - }); - - - it('swap outerHTML does not trigger htmx:afterSwap on original element', function() - { - this.server.respondWith("GET", "/test", 'Clicked!'); - var div = make('
    ') - div.addEventListener("htmx:afterSwap", function(){ - count++; - }) - div.click(); - var count = 0; - should.equal(byId("d1"), div); - this.server.respond(); - should.equal(byId("d1"), null); - count.should.equal(0); - }); - it('swap delete works properly', function() - { - this.server.respondWith("GET", "/test", 'Oops, deleted!'); - - var div = make('
    Foo
    ') - div.click(); - this.server.respond(); - should.equal(byId("d1"), null); - }); - - it('in presence of bad swap spec, it uses the default swap strategy', function() - { - var initialSwapStyle = htmx.config.defaultSwapStyle; - htmx.config.defaultSwapStyle = "outerHTML"; - try { - this.server.respondWith("GET", "/test", "Clicked!"); - - var div = make('
    ') - var b1 = byId("b1"); - b1.click(); - this.server.respond(); - div.innerHTML.should.equal('Clicked!'); - } finally { - htmx.config.defaultSwapStyle = initialSwapStyle; - } - }); - - it('hx-swap ignoreTitle works', function() - { - window.document.title = "Test Title"; - this.server.respondWith("GET", "/test", function (xhr) { - xhr.respond(200, {}, "htmx rocks!Clicked!"); - }); - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerText.should.equal("Clicked!"); - window.document.title.should.equal("Test Title"); - }); - -}) diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-sync.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-sync.js deleted file mode 100644 index 6f4d0d10dd1..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-sync.js +++ /dev/null @@ -1,224 +0,0 @@ -describe("hx-sync attribute", function(){ - beforeEach(function() { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function() { - this.server.restore(); - clearWorkArea(); - }); - - it('can use drop strategy', function() - { - var count = 0; - this.server.respondWith("GET", "/test", function(xhr){ - xhr.respond(200, {}, "Click " + count++); - }); - make('
    ' + - '
    ') - var b1 = byId("b1"); - var b2 = byId("b2"); - b1.click(); - b2.click(); - this.server.respond(); - this.server.respond(); - b1.innerHTML.should.equal('Click 0'); - b2.innerHTML.should.equal('Initial'); - }); - - it('defaults to the drop strategy', function() - { - var count = 0; - this.server.respondWith("GET", "/test", function(xhr){ - xhr.respond(200, {}, "Click " + count++); - }); - make('
    ' + - '
    ') - var b1 = byId("b1"); - var b2 = byId("b2"); - b1.click(); - b2.click(); - this.server.respond(); - this.server.respond(); - b1.innerHTML.should.equal('Click 0'); - b2.innerHTML.should.equal('Initial'); - }); - - it('can use replace strategy', function() - { - var count = 0; - this.server.respondWith("GET", "/test", function(xhr){ - xhr.respond(200, {}, "Click " + count++); - }); - make('
    ' + - '
    ') - var b1 = byId("b1"); - var b2 = byId("b2"); - b1.click(); - b2.click(); - this.server.respond(); - this.server.respond(); - b1.innerHTML.should.equal('Initial'); - b2.innerHTML.should.equal('Click 0'); - }); - - it('can use queue all strategy', function() - { - var count = 0; - this.server.respondWith("GET", "/test", function(xhr){ - xhr.respond(200, {}, "Click " + count++); - }); - make('
    ' + - ' ' + - '
    ') - var b1 = byId("b1"); - b1.click(); - - var b2 = byId("b2"); - b2.click(); - - var b3 = byId("b3"); - b3.click(); - - this.server.respond(); - b1.innerHTML.should.equal('Click 0'); - b2.innerHTML.should.equal('Initial'); - b3.innerHTML.should.equal('Initial'); - - this.server.respond(); - b1.innerHTML.should.equal('Click 0'); - b2.innerHTML.should.equal('Click 1'); - b3.innerHTML.should.equal('Initial'); - - this.server.respond(); - b1.innerHTML.should.equal('Click 0'); - b2.innerHTML.should.equal('Click 1'); - b3.innerHTML.should.equal('Click 2'); - }); - - it('can use queue last strategy', function() - { - var count = 0; - this.server.respondWith("GET", "/test", function(xhr){ - xhr.respond(200, {}, "Click " + count++); - }); - make('
    ' + - ' ' + - '
    ') - var b1 = byId("b1"); - b1.click(); - - var b2 = byId("b2"); - b2.click(); - - var b3 = byId("b3"); - b3.click(); - - this.server.respond(); - b1.innerHTML.should.equal('Click 0'); - b2.innerHTML.should.equal('Initial'); - b3.innerHTML.should.equal('Initial'); - - this.server.respond(); - b1.innerHTML.should.equal('Click 0'); - b2.innerHTML.should.equal('Initial'); - b3.innerHTML.should.equal('Click 1'); - - this.server.respond(); - b1.innerHTML.should.equal('Click 0'); - b2.innerHTML.should.equal('Initial'); - b3.innerHTML.should.equal('Click 1'); - }); - - it('can use queue first strategy', function() - { - var count = 0; - this.server.respondWith("GET", "/test", function(xhr){ - xhr.respond(200, {}, "Click " + count++); - }); - make('
    ' + - ' ' + - '
    ') - var b1 = byId("b1"); - b1.click(); - - var b2 = byId("b2"); - b2.click(); - - var b3 = byId("b3"); - b3.click(); - - this.server.respond(); - b1.innerHTML.should.equal('Click 0'); - b2.innerHTML.should.equal('Initial'); - b3.innerHTML.should.equal('Initial'); - - this.server.respond(); - b1.innerHTML.should.equal('Click 0'); - b2.innerHTML.should.equal('Click 1'); - b3.innerHTML.should.equal('Initial'); - - this.server.respond(); - b1.innerHTML.should.equal('Click 0'); - b2.innerHTML.should.equal('Click 1'); - b3.innerHTML.should.equal('Initial'); - }); - - it('can use abort strategy to end existing abortable request', function() - { - var count = 0; - this.server.respondWith("GET", "/test", function(xhr){ - xhr.respond(200, {}, "Click " + count++); - }); - make('
    ' + - '
    ') - var b1 = byId("b1"); - var b2 = byId("b2"); - b1.click(); - b2.click(); - this.server.respond(); - this.server.respond(); - b1.innerHTML.should.equal('Initial'); - b2.innerHTML.should.equal('Click 0'); - }); - - it('can use abort strategy to drop abortable request when one is in flight', function() - { - var count = 0; - this.server.respondWith("GET", "/test", function(xhr){ - xhr.respond(200, {}, "Click " + count++); - }); - make('
    ' + - '
    ') - var b1 = byId("b1"); - var b2 = byId("b2"); - b2.click(); - b1.click(); - this.server.respond(); - this.server.respond(); - b1.innerHTML.should.equal('Initial'); - b2.innerHTML.should.equal('Click 0'); - }); - - it('can abort a request programmatically', function() - { - var count = 0; - this.server.respondWith("GET", "/test", function(xhr){ - xhr.respond(200, {}, "Click " + count++); - }); - make('
    ' + - '
    ') - var b1 = byId("b1"); - var b2 = byId("b2"); - b1.click(); - b2.click(); - - htmx.trigger(b1, "htmx:abort"); - - this.server.respond(); - this.server.respond(); - b1.innerHTML.should.equal('Initial'); - b2.innerHTML.should.equal('Click 0'); - }); - -}) diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-target.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-target.js deleted file mode 100644 index efd3d1c7278..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-target.js +++ /dev/null @@ -1,244 +0,0 @@ -describe("hx-target attribute", function(){ - beforeEach(function() { - this.server = sinon.fakeServer.create(); - clearWorkArea(); - }); - afterEach(function() { - this.server.restore(); - clearWorkArea(); - }); - - it('targets an adjacent element properly', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - var btn = make('') - var div1 = make('
    ') - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal("Clicked!"); - }); - - it('targets a parent element properly', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - var div1 = make('
    ') - var btn = byId("b1") - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal("Clicked!"); - }); - - it('targets a `this` element properly', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - var div1 = make('
    ') - var btn = byId("b1") - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal("Clicked!"); - }); - - it('targets a `closest` element properly', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - var div1 = make('

    ') - var btn = byId("b1") - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal("Clicked!"); - }); - - it('targets a `closest` element properly w/ hyperscript syntax', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - var div1 = make('

    ') - var btn = byId("b1") - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal("Clicked!"); - }); - - it('targets a `find` element properly', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - var div1 = make('
    Click Me!
    ') - div1.click(); - this.server.respond(); - var span1 = byId("s1") - var span2 = byId("s2") - span1.innerHTML.should.equal("Clicked!"); - span2.innerHTML.should.equal(""); - }); - - it('targets a `find` element properly w/ hyperscript syntax', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - var div1 = make('
    Click Me!
    ') - div1.click(); - this.server.respond(); - var span1 = byId("s1") - var span2 = byId("s2") - span1.innerHTML.should.equal("Clicked!"); - span2.innerHTML.should.equal(""); - }); - - it('targets an inner element properly', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - var btn = make('') - var div1 = byId("d1") - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal("Clicked!"); - }); - - it('targets an inner element properly w/ hyperscript syntax', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - var btn = make('') - var div1 = byId("d1") - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal("Clicked!"); - }); - - it('handles bad target gracefully', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Click Me!"); - }); - - - it('targets an adjacent element properly w/ data-* prefix', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - var btn = make('') - var div1 = make('
    ') - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal("Clicked!"); - }); - - it('targets a `next` element properly', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - make('
    ' + - '
    ' + - ' ' + - '
    ' + - '
    ' + - '
    ') - var btn = byId("b1") - var div1 = byId("d1") - var div2 = byId("d2") - var div3 = byId("d3") - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal("Clicked!"); - div2.innerHTML.should.equal(""); - div3.innerHTML.should.equal(""); - }); - - it('targets a `next` element properly w/ hyperscript syntax', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - make('
    ' + - '
    ' + - ' ' + - '
    ' + - '
    ' + - '
    ') - var btn = byId("b1") - var div1 = byId("d1") - var div2 = byId("d2") - var div3 = byId("d3") - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal("Clicked!"); - div2.innerHTML.should.equal(""); - div3.innerHTML.should.equal(""); - }); - - it('targets a `previous` element properly', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - make('
    ' + - '
    ' + - ' ' + - '
    ' + - '
    ' + - '
    ') - var btn = byId("b1") - var div1 = byId("d1") - var div2 = byId("d2") - var div3 = byId("d3") - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal(""); - div2.innerHTML.should.equal(""); - div3.innerHTML.should.equal("Clicked!"); - }); - - it('targets a `previous` element properly w/ hyperscript syntax', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - make('
    ' + - '
    ' + - ' ' + - '
    ' + - '
    ' + - '
    ') - var btn = byId("b1") - var div1 = byId("d1") - var div2 = byId("d2") - var div3 = byId("d3") - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal(""); - div2.innerHTML.should.equal(""); - div3.innerHTML.should.equal("Clicked!"); - }); - - it('targets a `next` element properly without selector', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - make('
    ' + - '
    ' + - ' ' + - '
    ' + - '
    ' + - '
    ') - var btn = byId("b1") - var div1 = byId("d1") - var div2 = byId("d2") - var div3 = byId("d3") - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal("Clicked!"); - div2.innerHTML.should.equal(""); - div3.innerHTML.should.equal(""); - }); - - it('targets a `previous` element properly without selector', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - make('
    ' + - '
    ' + - ' ' + - '
    ' + - '
    ' + - '
    ') - var btn = byId("b1") - var div1 = byId("d1") - var div2 = byId("d2") - var div3 = byId("d3") - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal(""); - div2.innerHTML.should.equal(""); - div3.innerHTML.should.equal("Clicked!"); - }); -}) diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-trigger.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-trigger.js deleted file mode 100644 index f65f974b7d0..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-trigger.js +++ /dev/null @@ -1,1077 +0,0 @@ -describe("hx-trigger attribute", function(){ - beforeEach(function() { - this.server = sinon.fakeServer.create(); - clearWorkArea(); - }); - afterEach(function() { - this.server.restore(); - clearWorkArea(); - }); - - it('non-default value works', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - var form = make('
    Click Me!
    '); - form.click(); - form.innerHTML.should.equal("Click Me!"); - this.server.respond(); - form.innerHTML.should.equal("Clicked!"); - }); - - it('changed modifier works', function() - { - var requests = 0; - this.server.respondWith("GET", "/test", function (xhr) { - requests++; - xhr.respond(200, {}, "Requests: " + requests); - }); - var input = make(''); - var div = make('
    '); - input.click(); - this.server.respond(); - div.innerHTML.should.equal(""); - input.click(); - this.server.respond(); - div.innerHTML.should.equal(""); - input.value = "bar"; - input.click(); - this.server.respond(); - div.innerHTML.should.equal("Requests: 1"); - input.click(); - this.server.respond(); - div.innerHTML.should.equal("Requests: 1"); - }); - - it('changed modifier works along from clause with single input', function() - { - var requests = 0; - this.server.respondWith("GET", "/test", function (xhr) { - requests++; - xhr.respond(200, {}, "Requests: " + requests); - }); - var input = make(''); - make('
    ') - var div = make('
    '); - input.click(); - this.server.respond(); - div.innerHTML.should.equal(""); - input.click(); - this.server.respond(); - div.innerHTML.should.equal(""); - input.value = "bar"; - input.click(); - this.server.respond(); - div.innerHTML.should.equal("Requests: 1"); - input.click(); - this.server.respond(); - div.innerHTML.should.equal("Requests: 1"); - }); - - it('changed modifier works along from clause with two inputs', function() - { - var requests = 0; - this.server.respondWith("GET", "/test", function (xhr) { - requests++; - xhr.respond(200, {}, "Requests: " + requests); - }); - var input1 = make(''); - var input2 = make(''); - make('
    ') - var div = make('
    '); - - input1.click(); - this.server.respond(); - div.innerHTML.should.equal(""); - input2.click(); - this.server.respond(); - div.innerHTML.should.equal(""); - - input1.value = "bar"; - input2.click(); - this.server.respond(); - div.innerHTML.should.equal(""); - input1.click(); - this.server.respond(); - div.innerHTML.should.equal("Requests: 1"); - - input1.click(); - this.server.respond(); - div.innerHTML.should.equal("Requests: 1"); - input2.click(); - this.server.respond(); - div.innerHTML.should.equal("Requests: 1"); - - input2.value = "foo"; - input1.click(); - this.server.respond(); - div.innerHTML.should.equal("Requests: 1"); - input2.click(); - this.server.respond(); - div.innerHTML.should.equal("Requests: 2"); - }); - - it('once modifier works', function() - { - var requests = 0; - this.server.respondWith("GET", "/test", function (xhr) { - requests++; - xhr.respond(200, {}, "Requests: " + requests); - }); - var input = make(''); - var div = make('
    '); - input.click(); - this.server.respond(); - div.innerHTML.should.equal("Requests: 1"); - input.click(); - this.server.respond(); - div.innerHTML.should.equal("Requests: 1"); - input.value = "bar"; - input.click(); - this.server.respond(); - div.innerHTML.should.equal("Requests: 1"); - input.click(); - this.server.respond(); - div.innerHTML.should.equal("Requests: 1"); - }); - - it('once modifier works with multiple triggers', function() - { - var requests = 0; - this.server.respondWith("GET", "/test", function (xhr) { - requests++; - xhr.respond(200, {}, "Requests: " + requests); - }); - var input = make(''); - var div = make('
    '); - input.click(); - this.server.respond(); - div.innerHTML.should.equal("Requests: 1"); - input.click(); - this.server.respond(); - div.innerHTML.should.equal("Requests: 1"); - input.value = "bar"; - input.click(); - this.server.respond(); - div.innerHTML.should.equal("Requests: 1"); - input.click(); - this.server.respond(); - div.innerHTML.should.equal("Requests: 1"); - htmx.trigger(input, "foo"); - this.server.respond(); - div.innerHTML.should.equal("Requests: 2"); - }); - - it('polling works', function(complete) - { - var requests = 0; - this.server.respondWith("GET", "/test", function (xhr) { - requests++; - if (requests > 5) { - complete(); - // cancel polling with a - xhr.respond(286, {}, "Requests: " + requests); - } else { - xhr.respond(200, {}, "Requests: " + requests); - } - }); - this.server.autoRespond = true; - this.server.autoRespondAfter = 0; - make('
    '); - }); - - - it('non-default value works w/ data-* prefix', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - var form = make('
    Click Me!
    '); - form.click(); - form.innerHTML.should.equal("Click Me!"); - this.server.respond(); - form.innerHTML.should.equal("Clicked!"); - }); - - it('works with multiple events', function() - { - var requests = 0; - this.server.respondWith("GET", "/test", function (xhr) { - requests++; - xhr.respond(200, {}, "Requests: " + requests); - }); - var div = make('
    Requests: 0
    '); - div.innerHTML.should.equal("Requests: 0"); - this.server.respond(); - div.innerHTML.should.equal("Requests: 1"); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Requests: 2"); - }); - - it("parses spec strings", function() - { - var specExamples = { - "": [{trigger: 'click'}], - "every 1s": [{trigger: 'every', pollInterval: 1000}], - "every 0s": [{trigger: 'every', pollInterval: 0}], - "every 0ms": [{trigger: 'every', pollInterval: 0}], - "click": [{trigger: 'click'}], - "customEvent": [{trigger: 'customEvent'}], - "event changed": [{trigger: 'event', changed: true}], - "event once": [{trigger: 'event', once: true}], - "event throttle:1s": [{trigger: 'event', throttle: 1000}], - "event throttle:0s": [{trigger: 'event', throttle: 0}], - "event throttle:0ms": [{trigger: 'event', throttle: 0}], - "event throttle:1s, foo": [{trigger: 'event', throttle: 1000}, {trigger: 'foo'}], - "event delay:1s": [{trigger: 'event', delay: 1000}], - "event delay:1s, foo": [{trigger: 'event', delay: 1000}, {trigger: 'foo'}], - "event delay:0s, foo": [{trigger: 'event', delay: 0}, {trigger: 'foo'}], - "event delay:0ms, foo": [{trigger: 'event', delay: 0}, {trigger: 'foo'}], - "event changed once delay:1s": [{trigger: 'event', changed: true, once: true, delay: 1000}], - "event1,event2": [{trigger: 'event1'}, {trigger: 'event2'}], - "event1, event2": [{trigger: 'event1'}, {trigger: 'event2'}], - "event1 once, event2 changed": [{trigger: 'event1', once: true}, {trigger: 'event2', changed: true}], - "event1,": [{trigger: 'event1'}], - " ": [{trigger: 'click'}], - } - - for (var specString in specExamples) { - var div = make("
    "); - var spec = htmx._('getTriggerSpecs')(div); - spec.should.deep.equal(specExamples[specString], "Found : " + JSON.stringify(spec) + ", expected : " + JSON.stringify(specExamples[specString]) + " for spec: " + specString); - } - }); - - it('sets default trigger for forms', function() - { - var form = make('
    '); - var spec = htmx._('getTriggerSpecs')(form); - spec.should.deep.equal([{trigger: 'submit'}]); - }) - - it('sets default trigger for form elements', function() - { - var form = make(''); - var spec = htmx._('getTriggerSpecs')(form); - spec.should.deep.equal([{trigger: 'change'}]); - }) - - it('filters properly with false filter spec', function(){ - this.server.respondWith("GET", "/test", "Called!"); - var form = make('
    Not Called
    '); - form.click(); - form.innerHTML.should.equal("Not Called"); - var event = htmx._("makeEvent")('evt'); - form.dispatchEvent(event); - this.server.respond(); - form.innerHTML.should.equal("Not Called"); - }) - - it('filters properly with true filter spec', function(){ - this.server.respondWith("GET", "/test", "Called!"); - var form = make('
    Not Called
    '); - form.click(); - form.innerHTML.should.equal("Not Called"); - var event = htmx._("makeEvent")('evt'); - event.foo = true; - form.dispatchEvent(event); - this.server.respond(); - form.innerHTML.should.equal("Called!"); - }) - - it('filters properly compound filter spec', function(){ - this.server.respondWith("GET", "/test", "Called!"); - var div = make('
    Not Called
    '); - var event = htmx._("makeEvent")('evt'); - event.foo = true; - div.dispatchEvent(event); - this.server.respond(); - div.innerHTML.should.equal("Not Called"); - event.bar = true; - div.dispatchEvent(event); - this.server.respond(); - div.innerHTML.should.equal("Called!"); - }) - - it('can refer to target element in condition', function(){ - this.server.respondWith("GET", "/test", "Called!"); - var div = make('
    Not Called
    '); - var event = htmx._("makeEvent")('evt'); - div.dispatchEvent(event); - this.server.respond(); - div.innerHTML.should.equal("Not Called"); - div.classList.add("doIt"); - div.dispatchEvent(event); - this.server.respond(); - div.innerHTML.should.equal("Called!"); - }) - - it('can refer to target element in condition w/ equality', function(){ - this.server.respondWith("GET", "/test", "Called!"); - var div = make('
    Not Called
    '); - var event = htmx._("makeEvent")('evt'); - div.dispatchEvent(event); - this.server.respond(); - div.innerHTML.should.equal("Not Called"); - div.id = "foo"; - div.dispatchEvent(event); - this.server.respond(); - div.innerHTML.should.equal("Called!"); - }) - - it('negative condition', function(){ - this.server.respondWith("GET", "/test", "Called!"); - var div = make('
    Not Called
    '); - div.classList.add("disabled"); - var event = htmx._("makeEvent")('evt'); - div.dispatchEvent(event); - this.server.respond(); - div.innerHTML.should.equal("Not Called"); - div.classList.remove("disabled"); - div.dispatchEvent(event); - this.server.respond(); - div.innerHTML.should.equal("Called!"); - }) - - it('global function call works', function(){ - window.globalFun = function(evt) { - return evt.bar; - } - try { - this.server.respondWith("GET", "/test", "Called!"); - var div = make('
    Not Called
    '); - var event = htmx._("makeEvent")('evt'); - event.bar = false; - div.dispatchEvent(event); - this.server.respond(); - div.innerHTML.should.equal("Not Called"); - event.bar = true; - div.dispatchEvent(event); - this.server.respond(); - div.innerHTML.should.equal("Called!"); - } finally { - delete window.globalFun; - } - }) - - it('global property event filter works', function(){ - window.foo = { - bar:false - } - try { - this.server.respondWith("GET", "/test", "Called!"); - var div = make('
    Not Called
    '); - var event = htmx._("makeEvent")('evt'); - div.dispatchEvent(event); - this.server.respond(); - div.innerHTML.should.equal("Not Called"); - foo.bar = true; - div.dispatchEvent(event); - this.server.respond(); - div.innerHTML.should.equal("Called!"); - } finally { - delete window.foo; - } - }) - - it('global variable filter works', function(){ - try { - this.server.respondWith("GET", "/test", "Called!"); - var div = make('
    Not Called
    '); - var event = htmx._("makeEvent")('evt'); - div.dispatchEvent(event); - this.server.respond(); - div.innerHTML.should.equal("Not Called"); - foo = true; - div.dispatchEvent(event); - this.server.respond(); - div.innerHTML.should.equal("Called!"); - } finally { - delete window.foo; - } - }) - - it('can filter polling', function(complete){ - this.server.respondWith("GET", "/test", "Called!"); - window.foo = false; - var div = make('
    Not Called
    '); - var div2 = make('
    Not Called
    '); - this.server.autoRespond = true; - this.server.autoRespondAfter = 0; - setTimeout(function () { - div.innerHTML.should.equal("Not Called"); - div2.innerHTML.should.equal("Called!"); - delete window.foo; - complete(); - }, 100); - }) - - it('bad condition issues error', function(){ - this.server.respondWith("GET", "/test", "Called!"); - var div = make('
    Not Called
    '); - var errorEvent = null; - var handler = htmx.on("htmx:eventFilter:error", function (event) { - errorEvent = event; - }); - try { - var event = htmx._("makeEvent")('evt'); - div.dispatchEvent(event); - should.not.equal(null, errorEvent); - should.not.equal(null, errorEvent.detail.source); - console.log(errorEvent.detail.source); - } finally { - htmx.off("htmx:eventFilter:error", handler); - } - }) - - it('from clause works', function() - { - var requests = 0; - this.server.respondWith("GET", "/test", function (xhr) { - requests++; - xhr.respond(200, {}, "Requests: " + requests); - }); - var div2 = make('
    '); - var div1 = make('
    Requests: 0
    '); - div1.innerHTML.should.equal("Requests: 0"); - div1.click(); - this.server.respond(); - div1.innerHTML.should.equal("Requests: 0"); - div2.click(); - this.server.respond(); - div1.innerHTML.should.equal("Requests: 1"); - }); - - it('from clause works with body selector', function() - { - var requests = 0; - this.server.respondWith("GET", "/test", function (xhr) { - requests++; - xhr.respond(200, {}, "Requests: " + requests); - }); - var div1 = make('
    Requests: 0
    '); - div1.innerHTML.should.equal("Requests: 0"); - document.body.click(); - this.server.respond(); - div1.innerHTML.should.equal("Requests: 1"); - }); - - it('from clause works with document selector', function() - { - var requests = 0; - this.server.respondWith("GET", "/test", function (xhr) { - requests++; - xhr.respond(200, {}, "Requests: " + requests); - }); - var div1 = make('
    Requests: 0
    '); - div1.innerHTML.should.equal("Requests: 0"); - htmx.trigger(document, 'foo'); - this.server.respond(); - div1.innerHTML.should.equal("Requests: 1"); - }); - - it('from clause works with window selector', function() - { - var requests = 0; - this.server.respondWith("GET", "/test", function (xhr) { - requests++; - xhr.respond(200, {}, "Requests: " + requests); - }); - var div1 = make('
    Requests: 0
    '); - div1.innerHTML.should.equal("Requests: 0"); - htmx.trigger(window, 'foo'); - this.server.respond(); - div1.innerHTML.should.equal("Requests: 1"); - }); - - it('from clause works with closest clause', function() - { - var requests = 0; - this.server.respondWith("GET", "/test", function (xhr) { - requests++; - xhr.respond(200, {}, "Requests: " + requests); - }); - var div1 = make(''); - var a1 = byId('a1'); - a1.innerHTML.should.equal("Requests: 0"); - div1.click(); - this.server.respond(); - a1.innerHTML.should.equal("Requests: 1"); - }); - - it('from clause works with find clause', function() - { - var requests = 0; - this.server.respondWith("GET", "/test", function (xhr) { - requests++; - xhr.respond(200, {}, "Requests: " + requests); - }); - var div1 = make(''); - var a1 = byId('a1'); - a1.innerHTML.should.equal("Requests: 0"); - a1.click(); - this.server.respond(); - a1.innerHTML.should.equal("Requests: 1"); - }); - - it('from clause works with next', function() - { - var requests = 0; - this.server.respondWith("GET", "/test", function (xhr) { - requests++; - xhr.respond(200, {}, "Requests: " + requests); - }); - make('
    Requests: 0'); - var a1 = byId('a1'); - a1.innerHTML.should.equal("Requests: 0"); - a1.click(); - this.server.respond(); - a1.innerHTML.should.equal("Requests: 1"); - }); - - it('from clause works with previous', function() - { - var requests = 0; - this.server.respondWith("GET", "/test", function (xhr) { - requests++; - xhr.respond(200, {}, "Requests: " + requests); - }); - make('Requests: 0
    '); - var a1 = byId('a1'); - a1.innerHTML.should.equal("Requests: 0"); - a1.click(); - this.server.respond(); - a1.innerHTML.should.equal("Requests: 1"); - }); - - it('event listeners on other elements are removed when an element is swapped out', function() - { - var requests = 0; - this.server.respondWith("GET", "/test", function (xhr) { - requests++; - xhr.respond(200, {}, "Requests: " + requests); - }); - this.server.respondWith("GET", "/test2", "Clicked"); - - var div1 = make('
    ' + - '
    Requests: 0
    ' + - '
    '); - var div2 = byId("d2"); - - div2.innerHTML.should.equal("Requests: 0"); - document.body.click(); - this.server.respond(); - requests.should.equal(1); - - requests.should.equal(1); - - div1.click(); - this.server.respond(); - div1.innerHTML.should.equal("Clicked"); - - requests.should.equal(2); - - document.body.click(); - this.server.respond(); - - requests.should.equal(2); - }); - - it('multiple triggers with from clauses mixed in work', function() - { - var requests = 0; - this.server.respondWith("GET", "/test", function (xhr) { - requests++; - xhr.respond(200, {}, "Requests: " + requests); - }); - var div2 = make('
    '); - var div1 = make('
    Requests: 0
    '); - div1.innerHTML.should.equal("Requests: 0"); - div1.click(); - this.server.respond(); - div1.innerHTML.should.equal("Requests: 1"); - div2.click(); - this.server.respond(); - div1.innerHTML.should.equal("Requests: 2"); - }); - - it('event listeners can filter on target', function() - { - var requests = 0; - this.server.respondWith("GET", "/test", function (xhr) { - requests++; - xhr.respond(200, {}, "Requests: " + requests); - }); - - var div1 = make('
    ' + - '
    Requests: 0
    ' + - '
    ' + - '
    ' + - '
    '); - var div1 = byId("d1"); - var div2 = byId("d2"); - var div3 = byId("d3"); - - div1.innerHTML.should.equal("Requests: 0"); - document.body.click(); - this.server.respond(); - requests.should.equal(0); - - div1.click(); - this.server.respond(); - requests.should.equal(0); - - div2.click(); - this.server.respond(); - requests.should.equal(0); - - div3.click(); - this.server.respond(); - requests.should.equal(1); - - }); - - it('consume prevents event propagation', function() - { - this.server.respondWith("GET", "/foo", "foo"); - this.server.respondWith("GET", "/bar", "bar"); - var div = make("
    " + - "
    " + - "
    "); - - byId("d1").click(); - this.server.respond(); - - // should not have been replaced by click - byId("d1").parentElement.should.equal(div); - byId("d1").innerText.should.equal("bar"); - }); - - it('throttle prevents multiple requests from happening', function(done) - { - var requests = 0; - var server = this.server; - server.respondWith("GET", "/test", function (xhr) { - requests++; - xhr.respond(200, {}, "Requests: " + requests); - }); - server.respondWith("GET", "/bar", "bar"); - var div = make("
    "); - - div.click(); - server.respond(); - - div.click(); - server.respond(); - - div.click(); - server.respond(); - - div.click(); - server.respond(); - - // should not have been replaced by click - div.innerText.should.equal("Requests: 1"); - - setTimeout(function () { - div.click(); - server.respond(); - div.innerText.should.equal("Requests: 2"); - - div.click(); - server.respond(); - div.innerText.should.equal("Requests: 2"); - - done(); - }, 50); - }); - - it("A throttle of 0 does not multiple requests from happening", function (done) { - var requests = 0; - var server = this.server; - server.respondWith("GET", "/test", function (xhr) { - requests++; - xhr.respond(200, {}, "Requests: " + requests); - }); - server.respondWith("GET", "/bar", "bar"); - var div = make( - "
    " - ); - - div.click(); - server.respond(); - div.innerText.should.equal("Requests: 1"); - - div.click(); - server.respond(); - div.innerText.should.equal("Requests: 2"); - - div.click(); - server.respond(); - div.innerText.should.equal("Requests: 3"); - - div.click(); - server.respond(); - div.innerText.should.equal("Requests: 4"); - - done() - }); - - it('delay delays the request', function(done) - { - var requests = 0; - var server = this.server; - this.server.respondWith("GET", "/test", function (xhr) { - requests++; - xhr.respond(200, {}, "Requests: " + requests); - }); - this.server.respondWith("GET", "/bar", "bar"); - var div = make("
    "); - - div.click(); - this.server.respond(); - - div.click(); - this.server.respond(); - - div.click(); - this.server.respond(); - - div.click(); - this.server.respond(); - div.innerText.should.equal(""); - - setTimeout(function () { - server.respond(); - div.innerText.should.equal("Requests: 1"); - - div.click(); - server.respond(); - div.innerText.should.equal("Requests: 1"); - - done(); - }, 50); - }); - - it("A 0 delay does not delay the request", function (done) { - var requests = 0; - this.server.respondWith("GET", "/test", function (xhr) { - requests++; - xhr.respond(200, {}, "Requests: " + requests); - }); - this.server.respondWith("GET", "/bar", "bar"); - var div = make( - "
    " - ); - - div.click(); - this.server.respond(); - div.innerText.should.equal("Requests: 1"); - - div.click(); - this.server.respond(); - div.innerText.should.equal("Requests: 2"); - - div.click(); - this.server.respond(); - div.innerText.should.equal("Requests: 3"); - - div.click(); - this.server.respond(); - div.innerText.should.equal("Requests: 4"); - - done(); - }); - - - it('requests are queued with last one winning by default', function() - { - var requests = 0; - var server = this.server; - this.server.respondWith("GET", "/test", function (xhr) { - requests++; - xhr.respond(200, {}, "Requests: " + requests); - }); - this.server.respondWith("GET", "/bar", "bar"); - var div = make("
    "); - - div.click(); - div.click(); - div.click(); - this.server.respond(); - div.innerText.should.equal("Requests: 1"); - - this.server.respond(); - div.innerText.should.equal("Requests: 2"); - - this.server.respond(); - div.innerText.should.equal("Requests: 2"); - }); - - it('queue:all queues all requests', function() - { - var requests = 0; - var server = this.server; - this.server.respondWith("GET", "/test", function (xhr) { - requests++; - xhr.respond(200, {}, "Requests: " + requests); - }); - this.server.respondWith("GET", "/bar", "bar"); - var div = make("
    "); - - div.click(); - div.click(); - div.click(); - this.server.respond(); - div.innerText.should.equal("Requests: 1"); - - this.server.respond(); - div.innerText.should.equal("Requests: 2"); - - this.server.respond(); - div.innerText.should.equal("Requests: 3"); - }); - - - it('queue:first queues first request', function() - { - var requests = 0; - var server = this.server; - this.server.respondWith("GET", "/test", function (xhr) { - requests++; - xhr.respond(200, {}, "Requests: " + requests); - }); - this.server.respondWith("GET", "/bar", "bar"); - var div = make("
    "); - - div.click(); - div.click(); - div.click(); - this.server.respond(); - div.innerText.should.equal("Requests: 1"); - - this.server.respond(); - div.innerText.should.equal("Requests: 2"); - - this.server.respond(); - div.innerText.should.equal("Requests: 2"); - }); - - it('queue:none queues no requests', function() - { - var requests = 0; - var server = this.server; - this.server.respondWith("GET", "/test", function (xhr) { - requests++; - xhr.respond(200, {}, "Requests: " + requests); - }); - this.server.respondWith("GET", "/bar", "bar"); - var div = make("
    "); - - div.click(); - div.click(); - div.click(); - this.server.respond(); - div.innerText.should.equal("Requests: 1"); - - this.server.respond(); - div.innerText.should.equal("Requests: 1"); - - this.server.respond(); - div.innerText.should.equal("Requests: 1"); - }); - - it('load event works w/ positive filters', function() - { - this.server.respondWith("GET", "/test", "Loaded!"); - var div = make('
    Load Me!
    '); - div.innerHTML.should.equal("Load Me!"); - this.server.respond(); - div.innerHTML.should.equal("Loaded!"); - }); - - it('load event works w/ negative filters', function() - { - this.server.respondWith("GET", "/test", "Loaded!"); - var div = make('
    Load Me!
    '); - div.innerHTML.should.equal("Load Me!"); - this.server.respond(); - div.innerHTML.should.equal("Load Me!"); - }); - - it('reveal event works on two elements', function() - { - this.server.respondWith("GET", "/test1", "test 1"); - this.server.respondWith("GET", "/test2", "test 2"); - var div = make('
    '); - var div2 = make('
    '); - div.innerHTML.should.equal(""); - div2.innerHTML.should.equal(""); - htmx.trigger(div, 'revealed') - htmx.trigger(div2, 'revealed') - this.server.respondAll(); - div.innerHTML.should.equal("test 1"); - div2.innerHTML.should.equal("test 2"); - }); - - it('reveal event works when triggered by window', function() - { - this.server.respondWith("GET", "/test1", "test 1"); - var div = make('
    foo
    '); - div.innerHTML.should.equal("foo"); - this.server.respondAll(); - div.innerHTML.should.equal("test 1"); - }); - - it("fires the htmx:trigger event when an AJAX attribute is specified", function () { - var param = "foo" - var handler = htmx.on("htmx:trigger", function (evt) { - param = "bar" - }); - try { - this.server.respondWith("GET", "/test1", "test 1"); - var div = make(''); - div.click(); - should.equal(param, "bar"); - } finally { - htmx.off("htmx:trigger", handler); - } - }); - - it("fires the htmx:trigger event when no AJAX attribute is specified", function () { - var param = "foo" - var handler = htmx.on("htmx:trigger", function (evt) { - param = "bar" - }); - try { - var div = make(''); - div.click(); - should.equal(param, "bar"); - } finally { - htmx.off("htmx:trigger", handler); - } - }); - - it('filters support "this" reference to the current element', function(){ - this.server.respondWith("GET", "/test", "Called!"); - var form = make('
    Not Called
    '); - form.click(); - this.server.respond(); - form.innerHTML.should.equal("Not Called"); - - form.classList.add('bar'); - form.click(); - this.server.respond(); - form.innerHTML.should.equal("Called!"); - }) - - it("correctly handles CSS descendant combinators", function(){ - this.server.respondWith("GET", "/test", "Clicked!"); - - var outer = make(` -
    -
    -
    -
    -
    -
    Unclicked.
    -
    -
    Unclicked.
    -
    - `); - - var inner = byId("inner"); - var second = byId("second"); - var other = byId("other"); - - second.innerHTML.should.equal("Unclicked."); - other.innerHTML.should.equal("Unclicked."); - - inner.click(); - this.server.respond(); - - second.innerHTML.should.equal("Clicked!"); - other.innerHTML.should.equal("Clicked!"); - }) - - - it('correctly handles CSS descendant combinators in modifier target', function() { - this.server.respondWith('GET', '/test', 'Called'); - - document.addEventListener('htmx:syntax:error', function(evt) { - chai.assert.fail('htmx:syntax:error'); - }); - - make(''); - var div = make('
    Not Called
    '); - - byId('a1').click(); - this.server.respond(); - div.innerHTML.should.equal("Not Called"); - - byId('a2').click(); - this.server.respond(); - div.innerHTML.should.equal("Called"); - }); - - it('correctly handles CSS descendant combinators in modifier root', function() { - this.server.respondWith('GET', '/test', 'Called'); - - document.addEventListener('htmx:syntax:error', function(evt) { - chai.assert.fail('htmx:syntax:error'); - }); - - make('
    Not Called
    '); - }); - - it("uses trigger specs cache if defined", function () { - var initialCacheConfig = htmx.config.triggerSpecsCache - htmx.config.triggerSpecsCache = {} - - var specExamples = { - "every 1s": [{trigger: 'every', pollInterval: 1000}], - "click": [{trigger: 'click'}], - "customEvent": [{trigger: 'customEvent'}], - "event changed": [{trigger: 'event', changed: true}], - "event once": [{trigger: 'event', once: true}], - "event delay:1s": [{trigger: 'event', delay: 1000}], - "event throttle:1s": [{trigger: 'event', throttle: 1000}], - "event delay:1s, foo": [{trigger: 'event', delay: 1000}, {trigger: 'foo'}], - "event throttle:1s, foo": [{trigger: 'event', throttle: 1000}, {trigger: 'foo'}], - "event changed once delay:1s": [{trigger: 'event', changed: true, once: true, delay: 1000}], - "event1,event2": [{trigger: 'event1'}, {trigger: 'event2'}], - "event1, event2": [{trigger: 'event1'}, {trigger: 'event2'}], - "event1 once, event2 changed": [{trigger: 'event1', once: true}, {trigger: 'event2', changed: true}], - } - - for (var specString in specExamples) { - var div = make("
    "); - var spec = htmx._('getTriggerSpecs')(div); - spec.should.deep.equal(specExamples[specString], "Found : " + JSON.stringify(spec) + ", expected : " + JSON.stringify(specExamples[specString]) + " for spec: " + specString); - } - - Object.keys(htmx.config.triggerSpecsCache).length.should.greaterThan(0) - Object.keys(htmx.config.triggerSpecsCache).length.should.equal(Object.keys(specExamples).length) - - htmx.config.triggerSpecsCache = initialCacheConfig - }) - - it("correctly reuses trigger specs from the cache if defined", function () { - var initialCacheConfig = htmx.config.triggerSpecsCache - htmx.config.triggerSpecsCache = {} - - var triggerStr = "event changed once delay:1s" - var expectedSpec = [{trigger: 'event', changed: true, once: true, delay: 1000}] - - var div = make("
    "); - var spec = htmx._('getTriggerSpecs')(div); - spec.should.deep.equal(expectedSpec, "Found : " + JSON.stringify(spec) + ", expected : " + JSON.stringify(expectedSpec) + " for spec: " + triggerStr); - spec.push("This should be carried to further identical specs thanks to the cache") - - var div2 = make("
    "); - var spec2 = htmx._('getTriggerSpecs')(div2); - spec2.should.deep.equal(spec, "Found : " + JSON.stringify(spec) + ", expected : " + JSON.stringify(spec2) + " for cached spec: " + triggerStr); - - Object.keys(htmx.config.triggerSpecsCache).length.should.equal(1) - - htmx.config.triggerSpecsCache = initialCacheConfig - }) -}) diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-vals.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-vals.js deleted file mode 100644 index 4c7e2d335ce..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-vals.js +++ /dev/null @@ -1,300 +0,0 @@ -describe("hx-vals attribute", function() { - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it('basic hx-vals works', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make("
    ") - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('basic hx-vals works with braces', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make("
    ") - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('multiple hx-vals works', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - var params = getParameters(xhr); - params['v1'].should.equal("test"); - params['v2'].should.equal("42"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make("
    ") - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('hx-vals can be on parents', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - make("
    "); - var div = byId("d1"); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('hx-vals can override parents', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("best"); - xhr.respond(200, {}, "Clicked!") - }); - make("
    "); - var div = byId("d1"); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('hx-vals overrides inputs', function () { - this.server.respondWith("POST", "/include", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("best"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make("
    ") - var input = byId("i1") - input.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('hx-vals overrides hx-vars', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make("
    ") - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('basic hx-vals javascript: works', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make('
    ') - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('hx-vals works with braces', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make('
    ') - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('multiple hx-vals works', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - var params = getParameters(xhr); - params['v1'].should.equal("test"); - params['v2'].should.equal("42"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make('
    ') - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('hx-vals can be on parents', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - make('
    ') - var div = byId("d1"); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('hx-vals can override parents', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("best"); - xhr.respond(200, {}, "Clicked!") - }); - make('
    ') - var div = byId("d1"); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('hx-vals overrides inputs', function () { - this.server.respondWith("POST", "/include", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("best"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make('
    ') - var input = byId("i1") - input.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('hx-vals treats objects as JSON', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("{\"i2\":\"test\"}"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make("
    ") - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('basic hx-vals can be unset', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - var params = getParameters(xhr); - params.should.be.empty; - xhr.respond(200, {}, "Clicked!") - }); - make( - "
    \ -
    \ -
    " - ); - var div = byId("d1"); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('basic hx-vals with braces can be unset', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - var params = getParameters(xhr); - params.should.be.empty; - xhr.respond(200, {}, "Clicked!") - }); - make( - "
    \ -
    \ -
    " - ); - var div = byId("d1"); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('multiple hx-vals can be unset', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - var params = getParameters(xhr); - params.should.be.empty; - xhr.respond(200, {}, "Clicked!") - }); - make( - "
    \ -
    \ -
    " - ); - var div = byId("d1"); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('unsetting hx-vals maintains input values', function () { - this.server.respondWith("POST", "/include", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make( - "
    \ - \ -
    " - ) - var input = byId("i1") - input.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('javascript: is not evaluated when allowEval is false', function () { - var calledEvent = false; - var handler = htmx.on("htmx:evalDisallowedError", function(){ - calledEvent = true; - }); - try { - htmx.config.allowEval = false; - this.server.respondWith("POST", "/vars", function (xhr) { - var params = getParameters(xhr); - should.not.exist(params['i1']); - xhr.respond(200, {}, "Clicked!") - }); - var div = make('
    ') - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - } finally { - htmx.config.allowEval = true; - htmx.off("htmx:evalDisallowedError", handler); - } - calledEvent.should.equal(true); - }); - - it('js: is not evaluated when allowEval is false', function () { - var calledEvent = false; - var handler = htmx.on("htmx:evalDisallowedError", function(){ - calledEvent = true; - }); - try { - htmx.config.allowEval = false; - this.server.respondWith("POST", "/vars", function (xhr) { - var params = getParameters(xhr); - should.not.exist(params['i1']); - xhr.respond(200, {}, "Clicked!") - }); - var div = make('
    ') - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - } finally { - htmx.config.allowEval = true; - htmx.off("htmx:evalDisallowedError", handler); - } - calledEvent.should.equal(true); - }); -}); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-vars.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-vars.js deleted file mode 100644 index f9647c0a5c6..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-vars.js +++ /dev/null @@ -1,177 +0,0 @@ -describe("hx-vars attribute", function() { - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it('basic hx-vars works', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make('
    ') - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('hx-vars works with braces', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make('
    ') - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('multiple hx-vars works', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - var params = getParameters(xhr); - params['v1'].should.equal("test"); - params['v2'].should.equal("42"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make('
    ') - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('hx-vars can be on parents', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - make('
    ') - var div = byId("d1"); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('hx-vars can override parents', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("best"); - xhr.respond(200, {}, "Clicked!") - }); - make('
    ') - var div = byId("d1"); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('hx-vars overrides inputs', function () { - this.server.respondWith("POST", "/include", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("best"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make('
    ') - var input = byId("i1") - input.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('basic hx-vars can be unset', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - var params = getParameters(xhr); - params.should.be.empty; - xhr.respond(200, {}, "Clicked!") - }); - make( - "
    \ -
    \ -
    " - ); - var div = byId("d1"); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('basic hx-vars with braces can be unset', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - var params = getParameters(xhr); - params.should.be.empty; - xhr.respond(200, {}, "Clicked!") - }); - make( - "
    \ -
    \ -
    " - ); - var div = byId("d1"); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('multiple hx-vars can be unset', function () { - this.server.respondWith("POST", "/vars", function (xhr) { - var params = getParameters(xhr); - params.should.be.empty; - xhr.respond(200, {}, "Clicked!") - }); - make( - "
    \ -
    \ -
    " - ); - var div = byId("d1"); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('unsetting hx-vars maintains input values', function () { - this.server.respondWith("POST", "/include", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make( - "
    \ - \ -
    " - ) - var input = byId("i1") - input.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('is not evaluated when allowEval is false', function () { - var calledEvent = false; - var handler = htmx.on("htmx:evalDisallowedError", function(){ - calledEvent = true; - }); - try { - htmx.config.allowEval = false; - this.server.respondWith("POST", "/vars", function (xhr) { - var params = getParameters(xhr); - should.not.exist(params['i1']); - xhr.respond(200, {}, "Clicked!") - }); - var div = make('
    ') - div.click(); - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - } finally { - htmx.config.allowEval = true; - htmx.off("htmx:evalDisallowedError", handler); - } - calledEvent.should.equal(true); - }); -}); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-ws.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-ws.js deleted file mode 100644 index 4cd9651af7f..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/attributes/hx-ws.js +++ /dev/null @@ -1,77 +0,0 @@ -describe("hx-ws attribute", function() { - - function mockWebsocket() { - var listener; - var lastSent; - var wasClosed = false; - var mockSocket = { - addEventListener : function(message, l) { - listener = l; - }, - write : function(content) { - return listener({data:content}); - }, - send : function(data) { - lastSent = data; - }, - getLastSent : function() { - return lastSent; - }, - close : function() { - wasClosed = true; - }, - wasClosed : function () { - return wasClosed; - } - }; - return mockSocket; - } - - beforeEach(function () { - this.server = makeServer(); - var socket = mockWebsocket(); - this.socket = socket; - clearWorkArea(); - this.oldCreateWebSocket = htmx.createWebSocket; - htmx.createWebSocket = function(){ - return socket - }; - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - htmx.createWebSocket = this.oldCreateWebSocket; - }); - - it('handles a basic call back', function () { - var div = make('
    div1
    div2
    '); - this.socket.write("
    replaced
    ") - byId("d1").innerHTML.should.equal("replaced"); - byId("d2").innerHTML.should.equal("div2"); - }) - - it('handles a basic send', function () { - var div = make('
    div1
    '); - byId("d1").click(); - var lastSent = this.socket.getLastSent(); - var data = JSON.parse(lastSent); - data.HEADERS["HX-Request"].should.equal("true"); - }) - - it('is closed after removal', function () { - this.server.respondWith("GET", "/test", "Clicked!"); - var div = make('
    '); - div.click(); - this.server.respond(); - this.socket.wasClosed().should.equal(true) - }) - - it('is closed after removal with no close and activity', function () { - var div = make('
    '); - div.parentElement.removeChild(div); - this.socket.write("
    replaced
    ") - this.socket.wasClosed().should.equal(true) - }) - -}); - diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/ajax.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/ajax.js deleted file mode 100644 index 00e677df687..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/ajax.js +++ /dev/null @@ -1,1317 +0,0 @@ -describe("Core htmx AJAX Tests", function(){ - beforeEach(function() { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function() { - this.server.restore(); - clearWorkArea(); - }); - - // bootstrap test - it('issues a GET request on click and swaps content', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - }); - - it('processes inner content properly', function() - { - this.server.respondWith("GET", "/test", 'Click Me'); - this.server.respondWith("GET", "/test2", "Clicked!"); - - var div = make('
    ') - div.click(); - this.server.respond(); - div.innerHTML.should.equal('Click Me'); - var a = div.querySelector('a'); - a.click(); - this.server.respond(); - a.innerHTML.should.equal('Clicked!'); - }); - - it('handles swap outerHTML properly', function() - { - this.server.respondWith("GET", "/test", 'Click Me'); - this.server.respondWith("GET", "/test2", "Clicked!"); - - var div = make('
    ') - div.click(); - should.equal(byId("d1"), div); - this.server.respond(); - should.equal(byId("d1"), null); - byId("a1").click(); - this.server.respond(); - byId("a1").innerHTML.should.equal('Clicked!'); - }); - - it('handles beforebegin properly', function() - { - var i = 0; - this.server.respondWith("GET", "/test", function(xhr){ - i++; - xhr.respond(200, {}, '' + i + ''); - }); - this.server.respondWith("GET", "/test2", "*"); - - var div = make('
    *
    ') - var parent = div.parentElement; - div.click(); - this.server.respond(); - div.innerText.should.equal("*"); - removeWhiteSpace(parent.innerText).should.equal("1*"); - - byId("a1").click(); - this.server.respond(); - removeWhiteSpace(parent.innerText).should.equal("**"); - - div.click(); - this.server.respond(); - div.innerText.should.equal("*"); - removeWhiteSpace(parent.innerText).should.equal("*2*"); - - byId("a2").click(); - this.server.respond(); - removeWhiteSpace(parent.innerText).should.equal("***"); - }); - - it('handles afterbegin properly', function() - { - var i = 0; - this.server.respondWith("GET", "/test", function(xhr){ - i++; - xhr.respond(200, {}, "" + i); - }); - - var div = make('
    *
    ') - - div.click(); - this.server.respond(); - div.innerText.should.equal("1*"); - - div.click(); - this.server.respond(); - div.innerText.should.equal("21*"); - - div.click(); - this.server.respond(); - div.innerText.should.equal("321*"); - }); - - it('handles afterbegin properly with no initial content', function() - { - var i = 0; - this.server.respondWith("GET", "/test", function(xhr){ - i++; - xhr.respond(200, {}, "" + i); - }); - - var div = make('
    ') - - div.click(); - this.server.respond(); - div.innerText.should.equal("1"); - - div.click(); - this.server.respond(); - div.innerText.should.equal("21"); - - div.click(); - this.server.respond(); - div.innerText.should.equal("321"); - }); - - it('handles afterend properly', function() - { - var i = 0; - this.server.respondWith("GET", "/test", function(xhr){ - i++; - xhr.respond(200, {}, '' + i + ''); - }); - this.server.respondWith("GET", "/test2", "*"); - - var div = make('
    *
    ') - var parent = div.parentElement; - div.click(); - this.server.respond(); - div.innerText.should.equal("*"); - removeWhiteSpace(parent.innerText).should.equal("*1"); - - byId("a1").click(); - this.server.respond(); - removeWhiteSpace(parent.innerText).should.equal("**"); - - div.click(); - this.server.respond(); - div.innerText.should.equal("*"); - removeWhiteSpace(parent.innerText).should.equal("*2*"); - - byId("a2").click(); - this.server.respond(); - removeWhiteSpace(parent.innerText).should.equal("***"); - }); - - it('handles beforeend properly', function() - { - var i = 0; - this.server.respondWith("GET", "/test", function(xhr){ - i++; - xhr.respond(200, {}, "" + i); - }); - - var div = make('
    *
    ') - - div.click(); - this.server.respond(); - div.innerText.should.equal("*1"); - - div.click(); - this.server.respond(); - div.innerText.should.equal("*12"); - - div.click(); - this.server.respond(); - div.innerText.should.equal("*123"); - }); - - it('handles beforeend properly with no initial content', function() - { - var i = 0; - this.server.respondWith("GET", "/test", function(xhr){ - i++; - xhr.respond(200, {}, "" + i); - }); - - var div = make('
    ') - - div.click(); - this.server.respond(); - div.innerText.should.equal("1"); - - div.click(); - this.server.respond(); - div.innerText.should.equal("12"); - - div.click(); - this.server.respond(); - div.innerText.should.equal("123"); - }); - - it('handles hx-target properly', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - - var btn = make(''); - var target = make('Initial'); - btn.click(); - target.innerHTML.should.equal("Initial"); - this.server.respond(); - target.innerHTML.should.equal("Clicked!"); - }); - - it('handles 204 NO CONTENT responses properly', function() - { - this.server.respondWith("GET", "/test", [204, {}, "No Content!"]); - - var btn = make(''); - btn.click(); - btn.innerHTML.should.equal("Click Me!"); - this.server.respond(); - btn.innerHTML.should.equal("Click Me!"); - }); - - it('handles 304 NOT MODIFIED responses properly', function() - { - this.server.respondWith("GET", "/test-1", [200, {}, "Content for Tab 1"]); - this.server.respondWith("GET", "/test-2", [200, {}, "Content for Tab 2"]); - - var target = make('
    ') - var btn1 = make(''); - var btn2 = make(''); - - btn1.click(); - target.innerHTML.should.equal(""); - this.server.respond(); - target.innerHTML.should.equal("Content for Tab 1"); - - btn2.click(); - this.server.respond(); - target.innerHTML.should.equal("Content for Tab 2"); - - this.server.respondWith("GET", "/test-1", [304, {}, "Content for Tab 1"]); - this.server.respondWith("GET", "/test-2", [304, {}, "Content for Tab 2"]); - - btn1.click(); - this.server.respond(); - target.innerHTML.should.equal("Content for Tab 1"); - - btn2.click(); - this.server.respond(); - target.innerHTML.should.equal("Content for Tab 2"); - }); - - it('handles hx-trigger with non-default value', function() - { - this.server.respondWith("GET", "/test", "Clicked!"); - - var form = make('
    Click Me!
    '); - form.click(); - form.innerHTML.should.equal("Click Me!"); - this.server.respond(); - form.innerHTML.should.equal("Clicked!"); - }); - - it('handles hx-trigger with load event', function() - { - this.server.respondWith("GET", "/test", "Loaded!"); - var div = make('
    Load Me!
    '); - div.innerHTML.should.equal("Load Me!"); - this.server.respond(); - div.innerHTML.should.equal("Loaded!"); - }); - - it('sets the content type of the request properly', function (done) { - this.server.respondWith("GET", "/test", function(xhr){ - xhr.respond(200, {}, "done"); - xhr.overriddenMimeType.should.equal("text/html"); - done(); - }); - var div = make('
    Click Me!
    '); - div.click(); - this.server.respond(); - }); - - it('issues two requests when clicked twice before response', function() - { - var i = 1; - this.server.respondWith("GET", "/test", function (xhr) { - xhr.respond(200, {}, "click " + i); - i++ - }); - var div = make('
    '); - div.click(); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("click 1"); - this.server.respond(); - div.innerHTML.should.equal("click 2"); - }); - - it('issues two requests when clicked three times before response', function() - { - var i = 1; - this.server.respondWith("GET", "/test", function (xhr) { - xhr.respond(200, {}, "click " + i); - i++ - }); - var div = make('
    '); - div.click(); - div.click(); - div.click(); - this.server.respondAll(); - div.innerHTML.should.equal("click 2"); - }); - - it('properly handles hx-select for basic situation', function() - { - var i = 1; - this.server.respondWith("GET", "/test", "
    foo
    bar
    "); - var div = make('
    '); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("
    foo
    "); - }); - - it('properly handles hx-select for full html document situation', function() - { - this.server.respondWith("GET", "/test", "
    foo
    bar
    "); - var div = make('
    '); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("
    foo
    "); - }); - - it('properly settles attributes on interior elements', function(done) - { - this.server.respondWith("GET", "/test", "
    "); - var div = make("
    "); - div.click(); - this.server.respond(); - should.equal(byId("d1").getAttribute("width"), null); - setTimeout(function () { - should.equal(byId("d1").getAttribute("width"), "bar"); - done(); - }, 20); - }); - - it('properly settles attributes elements with single quotes in id', function(done) - { - this.server.respondWith("GET", "/test", "
    "); - var div = make("
    "); - div.click(); - this.server.respond(); - should.equal(byId("d1'").getAttribute("width"), null); - setTimeout(function () { - should.equal(byId("d1'").getAttribute("width"), "bar"); - done(); - }, 20); - }); - - it('properly settles attributes elements with double quotes in id', function(done) - { - this.server.respondWith("GET", "/test", "
    "); - var div = make("
    "); - div.click(); - this.server.respond(); - should.equal(byId("d1\"").getAttribute("width"), null); - setTimeout(function () { - should.equal(byId("d1\"").getAttribute("width"), "bar"); - done(); - }, 20); - }); - - it('properly handles multiple select input', function() - { - var values; - this.server.respondWith("Post", "/test", function (xhr) { - values = getParameters(xhr); - xhr.respond(204, {}, ""); - }); - - var form = make('
    ' + - ''+ - '
    '); - - form.click(); - this.server.respond(); - values.should.deep.equal({}); - - byId("m1").selected = true; - form.click(); - this.server.respond(); - values.should.deep.equal({multiSelect:"m1"}); - - byId("m1").selected = true; - byId("m3").selected = true; - form.click(); - this.server.respond(); - values.should.deep.equal({multiSelect:["m1", "m3"]}); - }); - - it('properly handles multiple select input when "multiple" attribute is empty string', function() - { - var values; - this.server.respondWith("Post", "/test", function (xhr) { - values = getParameters(xhr); - xhr.respond(204, {}, ""); - }); - - var form = make('
    ' + - '' + - '
    '); - - form.click(); - this.server.respond(); - values.should.deep.equal({}); - - byId("m1").selected = true; - form.click(); - this.server.respond(); - values.should.deep.equal({multiSelect:"m1"}); - - byId("m1").selected = true; - byId("m3").selected = true; - form.click(); - this.server.respond(); - values.should.deep.equal({multiSelect:["m1", "m3"]}); - }); - - it('properly handles two multiple select inputs w/ same name', function() - { - var values; - this.server.respondWith("Post", "/test", function (xhr) { - values = getParameters(xhr); - xhr.respond(204, {}, ""); - }); - - var form = make('
    ' + - ''+ - ''+ - '
    '); - - form.click(); - this.server.respond(); - values.should.deep.equal({}); - - byId("m1").selected = true; - form.click(); - this.server.respond(); - values.should.deep.equal({multiSelect:"m1"}); - - byId("m1").selected = true; - byId("m3").selected = true; - byId("m7").selected = true; - byId("m8").selected = true; - form.click(); - this.server.respond(); - values.should.deep.equal({multiSelect:["m1", "m3", "m7", "m8"]}); - }); - - it('properly handles multiple email input', function() - { - var values; - this.server.respondWith("Post", "/test", function (xhr) { - values = getParameters(xhr); - xhr.respond(204, {}, ""); - }); - - var form = make('
    ' + - ''+ - '
    '); - - form.click(); - this.server.respond(); - values.should.deep.equal({multiEmail: ''}); - - byId("multiEmail").value = 'foo@example.com'; - form.click(); - this.server.respond(); - values.should.deep.equal({multiEmail:"foo@example.com"}); - - byId("multiEmail").value = 'foo@example.com,bar@example.com'; - form.click(); - this.server.respond(); - values.should.deep.equal({multiEmail:"foo@example.com,bar@example.com"}); - }); - - it('properly handles checkbox inputs', function() - { - var values; - this.server.respondWith("Post", "/test", function (xhr) { - values = getParameters(xhr); - xhr.respond(204, {}, ""); - }); - - var form = make('
    ' + - ''+ - ''+ - ''+ - ''+ - ''+ - ''+ - '
    '); - - form.click(); - this.server.respond(); - values.should.deep.equal({}); - - byId("cb1").checked = true; - form.click(); - this.server.respond(); - values.should.deep.equal({c1:"cb1"}); - - byId("cb1").checked = true; - byId("cb2").checked = true; - form.click(); - this.server.respond(); - values.should.deep.equal({c1:["cb1", "cb2"]}); - - byId("cb1").checked = true; - byId("cb2").checked = true; - byId("cb3").checked = true; - form.click(); - this.server.respond(); - values.should.deep.equal({c1:["cb1", "cb2", "cb3"]}); - - byId("cb1").checked = true; - byId("cb2").checked = true; - byId("cb3").checked = true; - byId("cb4").checked = true; - form.click(); - this.server.respond(); - values.should.deep.equal({c1:["cb1", "cb2", "cb3"], c2:"cb4"}); - - byId("cb1").checked = true; - byId("cb2").checked = true; - byId("cb3").checked = true; - byId("cb4").checked = true; - byId("cb5").checked = true; - form.click(); - this.server.respond(); - values.should.deep.equal({c1:["cb1", "cb2", "cb3"], c2:["cb4", "cb5"]}); - - byId("cb1").checked = true; - byId("cb2").checked = true; - byId("cb3").checked = true; - byId("cb4").checked = true; - byId("cb5").checked = true; - byId("cb6").checked = true; - form.click(); - this.server.respond(); - values.should.deep.equal({c1:["cb1", "cb2", "cb3"], c2:["cb4", "cb5"], c3:"cb6"}); - - byId("cb1").checked = true; - byId("cb2").checked = false; - byId("cb3").checked = true; - byId("cb4").checked = false; - byId("cb5").checked = true; - byId("cb6").checked = true; - form.click(); - this.server.respond(); - values.should.deep.equal({c1:["cb1", "cb3"], c2:"cb5", c3:"cb6"}); - - }); - - it('text nodes dont screw up settling via variable capture', function() - { - this.server.respondWith("GET", "/test", "
    fooo"); - this.server.respondWith("GET", "/test2", "clicked"); - var div = make("
    "); - div.click(); - this.server.respond(); - byId("d1").click(); - this.server.respond(); - byId("d1").innerHTML.should.equal("clicked"); - }); - - it('script nodes evaluate', function() - { - var globalWasCalled = false; - window.callGlobal = function() { - globalWasCalled = true; - } - try { - this.server.respondWith("GET", "/test", "
    "); - var div = make("
    "); - div.click(); - this.server.respond(); - globalWasCalled.should.equal(true); - } finally { - delete window.callGlobal; - } - }); - - it('stand alone script nodes evaluate', function() - { - var globalWasCalled = false; - window.callGlobal = function() { - globalWasCalled = true; - } - try { - this.server.respondWith("GET", "/test", ""); - var div = make("
    "); - div.click(); - this.server.respond(); - globalWasCalled.should.equal(true); - } finally { - delete window.callGlobal; - } - }); - - it('script nodes can define global functions', function() - { - try { - window.foo = {} - this.server.respondWith("GET", "/test", ""); - var div = make("
    "); - div.click(); - this.server.respond(); - foo.bar().should.equal(42); - } finally { - delete foo; - } - }); - - it('child script nodes evaluate when children', function() - { - var globalWasCalled = false; - window.callGlobal = function() { - globalWasCalled = true; - } - try { - this.server.respondWith("GET", "/test", "
    "); - var div = make("
    "); - div.click(); - this.server.respond(); - globalWasCalled.should.equal(true); - } finally { - delete window.callGlobal; - } - }); - - it('child script nodes evaluate when first child', function() - { - var globalWasCalled = false; - window.callGlobal = function() { - globalWasCalled = true; - } - try { - this.server.respondWith("GET", "/test", "
    "); - var div = make("
    "); - div.click(); - this.server.respond(); - globalWasCalled.should.equal(true); - } finally { - delete window.callGlobal; - } - }); - - it('child script nodes evaluate when not explicitly marked javascript', function() - { - var globalWasCalled = false; - window.callGlobal = function() { - globalWasCalled = true; - } - try { - this.server.respondWith("GET", "/test", "
    "); - var div = make("
    "); - div.click(); - this.server.respond(); - globalWasCalled.should.equal(true); - } finally { - delete window.callGlobal; - } - }); - - it('script nodes do not evaluate when explicitly marked as something other than javascript', function() - { - var globalWasCalled = false; - window.callGlobal = function() { - globalWasCalled = true; - } - try { - this.server.respondWith("GET", "/test", "
    "); - var div = make("
    "); - div.click(); - this.server.respond(); - globalWasCalled.should.equal(false); - } finally { - delete window.callGlobal; - } - }); - - it('script nodes evaluate after swap', function() - { - window.callGlobal = function() { - console.log("Here..."); - window.tempVal = byId("d1").innerText - } - try { - this.server.respondWith("GET", "/test", "
    After settle...
    "); - var div = make("
    "); - div.click(); - this.server.respond(); - window.tempVal.should.equal("After settle..."); - } finally { - delete window.callGlobal; - delete window.tempVal; - } - }); - - it('script node exceptions do not break rendering', function() - { - this.skip("Rendering does not break, but the exception bubbles up and mocha reports it"); - this.server.respondWith("GET", "/test", "clicked"); - var div = make("
    "); - div.click(); - this.server.respond(); - div.innerText.should.equal("clicked"); - console.log(div.innerText); - console.log("here"); - }); - - it('allows empty verb values', function() - { - var path = null; - var div = make("
    "); - htmx.on(div, "htmx:configRequest", function (evt) { - path = evt.detail.path; - return false; - }); - div.click(); - this.server.respond(); - path.should.not.be.null; - }); - - it('allows blank verb values', function() - { - var path = null; - var div = make("
    "); - htmx.on(div, "htmx:configRequest", function (evt) { - path = evt.detail.path; - return false; - }); - div.click(); - this.server.respond(); - path.should.not.be.null; - }); - - it('input values are not settle swapped (causes flicker)', function() - { - this.server.respondWith("GET", "/test", ""); - var input = make(""); - input.click(); - this.server.respond(); - input = byId('i1'); - input.value.should.equal('bar'); - }); - - it('autofocus attribute works properly', function() - { - this.server.respondWith("GET", "/test", ""); - var input = make(""); - input.focus(); - input.click(); - document.activeElement.should.equal(input); - this.server.respond(); - var input2 = byId('i2'); - document.activeElement.should.equal(input2); - }); - - it('autofocus attribute works properly w/ child', function() - { - this.server.respondWith("GET", "/test", "
    "); - var input = make(""); - input.focus(); - input.click(); - document.activeElement.should.equal(input); - this.server.respond(); - var input2 = byId('i2'); - document.activeElement.should.equal(input2); - }); - - it('autofocus attribute works properly w/ true value', function() - { - this.server.respondWith("GET", "/test", "
    "); - var input = make(""); - input.focus(); - input.click(); - document.activeElement.should.equal(input); - this.server.respond(); - var input2 = byId('i2'); - document.activeElement.should.equal(input2); - }); - - it('multipart/form-data encoding works', function() - { - this.server.respondWith("POST", "/test", function(xhr){ - should.equal(xhr.requestHeaders['Content-Type'], undefined); - if (xhr.requestBody.get) { //IE 11 does not support - xhr.requestBody.get("i1").should.equal('foo'); - } - xhr.respond(200, {}, "body: " + xhr.requestBody); - }); - var form = make("
    " + - "" + - "
    "); - form.focus(); - form.click(); - this.server.respond(); - }); - - it('removed elements do not issue requests', function() - { - var count = 0; - this.server.respondWith("GET", "/test", function (xhr) { - count++; - xhr.respond(200, {}, ""); - }); - var btn = make('') - htmx.remove(btn); - btn.click(); - this.server.respond(); - count.should.equal(0); - }); - - it('title tags update title', function() - { - this.server.respondWith("GET", "/test", function (xhr) { - xhr.respond(200, {}, "htmx rocks!Clicked!"); - }); - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerText.should.equal("Clicked!"); - window.document.title.should.equal("htmx rocks!"); - }); - - it('svg title tags do not update title', function() - { - var originalTitle = window.document.title - this.server.respondWith("GET", "/test", function (xhr) { - xhr.respond(200, {}, "" + originalTitle + "UPDATE" + "Clicked!"); - }); - var btn = make('') - btn.click(); - this.server.respond(); - if (supportsSvgTitles()) { // IE 11 - btn.innerText.should.equal("Clicked!"); - } - window.document.title.should.equal(originalTitle); - }); - - it('first title tag outside svg title tags updates title', function() - { - var originalTitle = window.document.title - var newTitle = originalTitle + "!!!"; - this.server.respondWith("GET", "/test", function (xhr) { - xhr.respond(200, {}, "" + newTitle + "fooClicked!x"); - }); - var btn = make('') - btn.click(); - this.server.respond(); - if (supportsSvgTitles()) { // IE 11 - btn.innerText.should.equal("Clicked!"); - } - window.document.title.should.equal(newTitle); - }); - - it('title update does not URL escape', function() - { - this.server.respondWith("GET", "/test", function (xhr) { - xhr.respond(200, {}, "</> htmx rocks!Clicked!"); - }); - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerText.should.equal("Clicked!"); - window.document.title.should.equal(" htmx rocks!"); - }); - - it('by default 400 content is not swapped', function() - { - this.server.respondWith("GET", "/test", function (xhr) { - xhr.respond(400, {}, "Clicked!"); - }); - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerText.should.equal("Click Me!"); - }); - - it('400 content can be swapped if configured to do so', function() - { - var handler = htmx.on("htmx:beforeSwap", function (event) { - if (event.detail.xhr.status === 400) { - event.detail.shouldSwap = true; - } - }); - - this.server.respondWith("GET", "/test", function (xhr) { - xhr.respond(400, {}, "Clicked!"); - }); - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerText.should.equal("Clicked!"); - htmx.off("htmx:beforeSwap", handler); - }); - - it('400 content can be retargeted if configured to do so', function() - { - var handler = htmx.on("htmx:beforeSwap", function (event) { - if (event.detail.xhr.status === 400) { - event.detail.shouldSwap = true; - event.detail.target = byId('d1') - } - }); - - this.server.respondWith("GET", "/test", function (xhr) { - xhr.respond(400, {}, "Clicked!"); - }); - var btn = make('') - var div = make('
    ') - btn.click(); - this.server.respond(); - div.innerText.should.equal("Clicked!"); - htmx.off("htmx:beforeSwap", handler); - }); - - it('errors are triggered only on 400+', function() - { - var errors = 0; - var handler = htmx.on("htmx:responseError", function(){ - errors++; - }) - this.server.respondWith("GET", "/test1", function (xhr) { - xhr.respond(204, {}, "Clicked!"); - }); - this.server.respondWith("GET", "/test2", function (xhr) { - xhr.respond(400, {}, "Clicked!"); - }); - var btn1 = make('') - var btn2 = make('') - btn1.click(); - btn2.click(); - this.server.respond(); - this.server.respond(); - errors.should.equal(1); - htmx.off("htmx:responseError", handler); - }); - - - it('content can be modified if configured to do so', function() - { - var handler = htmx.on("htmx:beforeSwap", function (event) { - if (event.detail.xhr.status === 400) { - event.detail.shouldSwap = true; - event.detail.serverResponse = event.detail.serverResponse + "!!"; - } - }); - - this.server.respondWith("GET", "/test", function (xhr) { - xhr.respond(400, {}, "Clicked!"); - }); - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerText.should.equal("Clicked!!!"); - htmx.off("htmx:beforeSwap", handler); - }); - - it('scripts w/ src attribute are properly loaded', function(done) - { - try { - this.server.respondWith("GET", "/test", ""); - var div = make("
    "); - div.click(); - this.server.respond(); - byId("setGlobalScript").addEventListener("load", function () { - window.globalWasCalled.should.equal(true); - delete window.globalWasCalled; - done(); - }) - } finally { - delete window.globalWasCalled; - } - }); - - it('should load tags with colon in their names', function() { - this.server.respondWith('GET', '/test', 'Foobar'); - - var btn = make(''); - btn.click(); - this.server.respond(); - - btn.innerHTML.should.equal('Foobar'); - }); - - it('properly handles clicked submit button with a value inside a htmx form', function () { - var values; - this.server.respondWith("Post", "/test", function (xhr) { - values = getParameters(xhr); - xhr.respond(204, {}, ""); - }); - - make('
    ' + - '' + - '' + - '
    '); - - byId("submit").click(); - this.server.respond(); - values.should.deep.equal({t1: 'textValue', b1: 'buttonValue'}); - }) - - it('properly handles clicked submit input with a value inside a htmx form', function () { - var values; - this.server.respondWith("Post", "/test", function (xhr) { - values = getParameters(xhr); - xhr.respond(204, {}, ""); - }); - - make('
    ' + - '' + - '' + - '
    '); - - byId("submit").click(); - this.server.respond(); - values.should.deep.equal({t1: 'textValue', b1: 'buttonValue'}); - }) - - it('properly handles clicked submit button with a value inside a non-htmx form', function () { - var values; - this.server.respondWith("Post", "/test", function (xhr) { - values = getParameters(xhr); - xhr.respond(204, {}, ""); - }); - - make('
    ' + - '' + - '' + - '
    '); - - byId("submit").click(); - this.server.respond(); - values.should.deep.equal({t1: 'textValue', b1: 'buttonValue'}); - }) - - it('properly handles clicked submit input with a value inside a non-htmx form', function () { - var values; - this.server.respondWith("Post", "/test", function (xhr) { - values = getParameters(xhr); - xhr.respond(204, {}, ""); - }); - - make('
    ' + - '' + - '' + - '
    '); - - byId("submit").click(); - this.server.respond(); - values.should.deep.equal({t1: 'textValue', b1: 'buttonValue'}); - }) - - it('properly handles clicked submit button with a value outside a htmx form', function () { - if (!supportsFormAttribute()) { - this._runnable.title += " - Skipped as IE11 doesn't support form attribute" - this.skip() - return - } - var values; - this.server.respondWith("Post", "/test", function (xhr) { - values = getParameters(xhr); - xhr.respond(204, {}, ""); - }); - - make('
    ' + - '' + - '
    ' + - ''); - - byId("submit").click(); - this.server.respond(); - values.should.deep.equal({t1: 'textValue', b1: 'buttonValue'}); - }) - - it('properly handles clicked submit input with a value outside a htmx form', function () { - if (!supportsFormAttribute()) { - this._runnable.title += " - Skipped as IE11 doesn't support form attribute" - this.skip() - return - } - var values; - this.server.respondWith("Post", "/test", function (xhr) { - values = getParameters(xhr); - xhr.respond(204, {}, ""); - }); - - make('
    ' + - '' + - '
    ' + - ''); - - byId("submit").click(); - this.server.respond(); - values.should.deep.equal({t1: 'textValue', b1: 'buttonValue'}); - }) - - it('properly handles clicked submit button with a value stacking with regular input', function () { - var values; - this.server.respondWith("Post", "/test", function (xhr) { - values = getParameters(xhr); - xhr.respond(204, {}, ""); - }); - - make('
    ' + - '' + - '' + - '' + - '' + - '
    '); - - byId("btnA").click(); - this.server.respond(); - values.should.deep.equal({action: 'A'}); - - byId("btnB").click(); - this.server.respond(); - values.should.deep.equal({action: ['A', 'B']}); - - byId("btnC").click(); - this.server.respond(); - values.should.deep.equal({action: ['A', 'C']}); - }) - - it('properly handles clicked submit input with a value stacking with regular input', function () { - var values; - this.server.respondWith("Post", "/test", function (xhr) { - values = getParameters(xhr); - xhr.respond(204, {}, ""); - }); - - make('
    ' + - '' + - 'A' + - 'B' + - 'C' + - '
    '); - - byId("btnA").click(); - this.server.respond(); - values.should.deep.equal({action: 'A'}); - - byId("btnB").click(); - this.server.respond(); - values.should.deep.equal({action: ['A', 'B']}); - - byId("btnC").click(); - this.server.respond(); - values.should.deep.equal({action: ['A', 'C']}); - }) - - it('properly handles clicked submit button with a value inside a form, referencing another form', function () { - if (!supportsFormAttribute()) { - this._runnable.title += " - Skipped as IE11 doesn't support form attribute" - this.skip() - return - } - var values; - this.server.respondWith("Post", "/test", function (xhr) { - values = getParameters(xhr); - xhr.respond(204, {}, ""); - }); - - make('
    ' + - '' + - '' + - '
    ' + - '
    ' + - '' + - '
    '); - - byId("submit").click(); - this.server.respond(); - values.should.deep.equal({t1: 'textValue', b1: ['inputValue', 'buttonValue']}); - }) - - it('properly handles clicked submit input with a value inside a form, referencing another form', function () { - if (!supportsFormAttribute()) { - this._runnable.title += " - Skipped as IE11 doesn't support form attribute" - this.skip() - return - } - var values; - this.server.respondWith("Post", "/test", function (xhr) { - values = getParameters(xhr); - xhr.respond(204, {}, ""); - }); - - make('
    ' + - '' + - '' + - '
    ' + - '
    ' + - '' + - '
    '); - - byId("submit").click(); - this.server.respond(); - values.should.deep.equal({t1: 'textValue', b1: ['inputValue', 'buttonValue']}); - }) - - it('properly handles inputs external to form', function () { - var values; - this.server.respondWith("Post", "/test", function (xhr) { - values = getParameters(xhr); - xhr.respond(204, {}, ""); - }); - - make('
    ' + - ' ' + - '
    ' + - '' + - '' + - ''); - - byId("submit").click(); - this.server.respond(); - values.should.deep.equal({t1: 'textValue', b1: ['inputValue', 'buttonValue'], s1: "selectValue"}); - }) - - it('handles form post with button formmethod dialog properly', function () { - var values; - this.server.respondWith("POST", "/test", function (xhr) { - values = getParameters(xhr); - xhr.respond(200, {}, ""); - }); - - make('
    '); - - byId("submit").click(); - this.server.respond(); - values.should.deep.equal({ foo: 'bar' }); - }) - - it('handles form get with button formmethod dialog properly', function () { - var responded = false; - this.server.respondWith("GET", "/test", function (xhr) { - responded = true; - xhr.respond(200, {}, ""); - }); - - make('
    '); - - byId("submit").click(); - this.server.respond(); - responded.should.equal(true); - }) - - it("can associate submit buttons from outside a form with the current version of the form after swap", function(){ - const template = '
    \n' + - '\n' + - '\n' + - '
    \n' + - ''; - - var values - this.server.respondWith("/test", function (xhr) { - values = getParameters(xhr); - xhr.respond(200, {}, template); - }); - make(template); - const button = byId("outside"); - button.focus(); - button.click(); - this.server.respond(); - values.should.deep.equal({name: "", outside: ""}); - button.focus(); - button.click(); - this.server.respond(); - values.should.deep.equal({name: "", outside: ""}); - }) -}) diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/api.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/api.js deleted file mode 100644 index 431633d6332..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/api.js +++ /dev/null @@ -1,390 +0,0 @@ -describe("Core htmx API test", function(){ - beforeEach(function() { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function() { - this.server.restore(); - clearWorkArea(); - }); - - it('should find properly', function(){ - var div = make("
    "); - div.should.equal(htmx.find("#d1")); - div.should.equal(htmx.find(".c1")); - div.should.equal(htmx.find(".c2")); - div.should.equal(htmx.find(".c1.c2")); - }); - - it('should find properly from elt', function(){ - var div = make("
    "); - htmx.find(div, "a").id.should.equal('a1'); - }); - - it('should find all properly', function(){ - var div = make("
    "); - htmx.findAll(".c1").length.should.equal(3); - htmx.findAll(".c2").length.should.equal(2); - htmx.findAll(".c3").length.should.equal(1); - }); - - it('should find all properly from elt', function(){ - var div = make("
    "); - htmx.findAll(div, ".c1").length.should.equal(3); - htmx.findAll(div, ".c2").length.should.equal(2); - htmx.findAll(div,".c3").length.should.equal(1); - }); - - it('should find closest element properly', function () { - var div = make("
    "); - var a = htmx.find(div, "a"); - htmx.closest(a, "div").should.equal(div); - }); - - it('should remove element properly', function () { - var div = make("
    "); - var a = htmx.find(div, "a"); - htmx.remove(a); - div.innerHTML.should.equal(""); - }); - - it('should remove element properly w/ selector', function () { - var div = make("
    "); - var a = htmx.find(div, "a"); - htmx.remove("#a1"); - div.innerHTML.should.equal(""); - }); - - it('should add class properly', function () { - var div = make("
    "); - div.classList.contains("foo").should.equal(false); - htmx.addClass(div, "foo"); - div.classList.contains("foo").should.equal(true); - }); - - - it('should add class properly w/ selector', function () { - var div = make("
    "); - div.classList.contains("foo").should.equal(false); - htmx.addClass("#div1", "foo"); - div.classList.contains("foo").should.equal(true); - }); - - it('should add class properly after delay', function (done) { - var div = make("
    "); - div.classList.contains("foo").should.equal(false); - htmx.addClass(div, "foo", 10); - div.classList.contains("foo").should.equal(false); - setTimeout(function () { - div.classList.contains("foo").should.equal(true); - done(); - }, 20); - }); - - it('should remove class properly', function () { - var div = make("
    "); - htmx.addClass(div, "foo"); - div.classList.contains("foo").should.equal(true); - htmx.removeClass(div, "foo"); - div.classList.contains("foo").should.equal(false); - }); - - it('should remove class properly w/ selector', function () { - var div = make("
    "); - htmx.addClass(div, "foo"); - div.classList.contains("foo").should.equal(true); - htmx.removeClass("#div1", "foo"); - div.classList.contains("foo").should.equal(false); - }); - - it('should add class properly after delay', function (done) { - var div = make("
    "); - htmx.addClass(div, "foo"); - div.classList.contains("foo").should.equal(true); - htmx.removeClass(div, "foo", 10); - div.classList.contains("foo").should.equal(true); - setTimeout(function () { - div.classList.contains("foo").should.equal(false); - done(); - }, 20); - }); - - it('should toggle class properly', function () { - var div = make("
    "); - div.classList.contains("foo").should.equal(false); - htmx.toggleClass(div, "foo"); - div.classList.contains("foo").should.equal(true); - htmx.toggleClass(div, "foo"); - div.classList.contains("foo").should.equal(false); - }); - - it('should toggle class properly w/ selector', function () { - var div = make("
    "); - div.classList.contains("foo").should.equal(false); - htmx.toggleClass("#div1", "foo"); - div.classList.contains("foo").should.equal(true); - htmx.toggleClass("#div1", "foo"); - div.classList.contains("foo").should.equal(false); - }); - - it('should take class properly', function () { - var div1 = make("
    "); - var div2 = make("
    "); - var div3 = make("
    "); - - div1.classList.contains("foo").should.equal(false); - div2.classList.contains("foo").should.equal(false); - div3.classList.contains("foo").should.equal(false); - - htmx.takeClass(div1, "foo"); - - div1.classList.contains("foo").should.equal(true); - div2.classList.contains("foo").should.equal(false); - div3.classList.contains("foo").should.equal(false); - - htmx.takeClass(div2, "foo"); - - div1.classList.contains("foo").should.equal(false); - div2.classList.contains("foo").should.equal(true); - div3.classList.contains("foo").should.equal(false); - - htmx.takeClass(div3, "foo"); - - div1.classList.contains("foo").should.equal(false); - div2.classList.contains("foo").should.equal(false); - div3.classList.contains("foo").should.equal(true); - }); - - it('should take class properly w/ selector', function () { - var div1 = make("
    "); - var div2 = make("
    "); - var div3 = make("
    "); - - div1.classList.contains("foo").should.equal(false); - div2.classList.contains("foo").should.equal(false); - div3.classList.contains("foo").should.equal(false); - - htmx.takeClass("#div1", "foo"); - - div1.classList.contains("foo").should.equal(true); - div2.classList.contains("foo").should.equal(false); - div3.classList.contains("foo").should.equal(false); - - htmx.takeClass("#div2", "foo"); - - div1.classList.contains("foo").should.equal(false); - div2.classList.contains("foo").should.equal(true); - div3.classList.contains("foo").should.equal(false); - - htmx.takeClass("#div3", "foo"); - - div1.classList.contains("foo").should.equal(false); - div2.classList.contains("foo").should.equal(false); - div3.classList.contains("foo").should.equal(true); - }); - - it('eval can be suppressed', function () { - var calledEvent = false; - var handler = htmx.on("htmx:evalDisallowedError", function(){ - calledEvent = true; - }); - try { - htmx.config.allowEval = false; - should.equal(htmx._("tokenizeString"), undefined); - } finally { - htmx.config.allowEval = true; - htmx.off("htmx:evalDisallowedError", handler); - } - calledEvent.should.equal(true); - }); - - it('ajax api works', function() - { - this.server.respondWith("GET", "/test", "foo!"); - var div = make("
    "); - htmx.ajax("GET", "/test", div) - this.server.respond(); - div.innerHTML.should.equal("foo!"); - }); - - it('ajax api works by ID', function() - { - this.server.respondWith("GET", "/test", "foo!"); - var div = make("
    "); - htmx.ajax("GET", "/test", "#d1") - this.server.respond(); - div.innerHTML.should.equal("foo!"); - }); - - it('ajax api works with swapSpec', function() - { - this.server.respondWith("GET", "/test", "

    foo!

    "); - var div = make("
    "); - htmx.ajax("GET", "/test", {target: "#target", swap:"outerHTML"}); - this.server.respond(); - div.innerHTML.should.equal('

    foo!

    '); - }); - - it('ajax api works with select', function() - { - this.server.respondWith("GET", "/test", "
    foo
    bar
    "); - var div = make("
    "); - htmx.ajax("GET", "/test", {target: "#target", select: "#d2"}); - this.server.respond(); - div.innerHTML.should.equal('
    bar
    '); - }); - - it('ajax api works with Hx-Select overrides select', function() - { - this.server.respondWith("GET", "/test", [200, {"HX-Reselect": "#d2"}, "
    foo
    bar
    "]); - var div = make("
    "); - htmx.ajax("GET", "/test", {target: "#target", select: "#d1"}); - this.server.respond(); - div.innerHTML.should.equal('
    bar
    '); - }); - - it('ajax returns a promise', function(done) - { - // in IE we do not return a promise - if (typeof Promise !== "undefined") { - this.server.respondWith("GET", "/test", "foo!"); - var div = make("
    "); - var promise = htmx.ajax("GET", "/test", "#d1"); - this.server.respond(); - div.innerHTML.should.equal("foo!"); - promise.then(function(){ - done(); - }) - } else { - done(); - } - }); - - it('ajax api can pass parameters', function() - { - this.server.respondWith("POST", "/test", function (xhr) { - var params = getParameters(xhr); - params['i1'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make("
    "); - htmx.ajax("POST", "/test", {target:"#d1", values:{i1: 'test'}}) - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('ajax api Content-Type header is application/x-www-form-urlencoded', function(){ - - this.server.respondWith("POST", "/test", function (xhr) { - var params = getParameters(xhr); - xhr.requestHeaders['Content-Type'].should.equal('application/x-www-form-urlencoded;charset=utf-8'); - params['i1'].should.equal("test"); - xhr.respond(200, {}, "Clicked!") - }); - var div = make("
    "); - htmx.ajax("POST", "/test", {target:"#d1", values:{i1: 'test'}}) - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - it('ajax api Content-Type header override to application/json', function(){ - - this.server.respondWith("POST", "/test", function (xhr) { - var params = getParameters(xhr); - xhr.requestHeaders['Content-Type'].should.equal('application/json;charset=utf-8'); - params['i1'].should.equal("test"); - xhr.respond(200, {}, "Clicked!"); - }); - - var div = make("
    "); - htmx.ajax('POST',"/test", { - target:'#d1', - swap:'innerHTML', - headers: { - 'Content-Type': 'application/json' - }, - values:{i1: 'test'} - }) - - this.server.respond(); - div.innerHTML.should.equal("Clicked!"); - }); - - - it('can re-init with new attributes', function () { - this.server.respondWith("PATCH", "/test", "patch"); - this.server.respondWith("DELETE", "/test", "delete"); - - var div = make('
    click me
    '); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("patch"); - - div.removeAttribute("hx-patch"); - div.setAttribute("hx-delete", "/test"); - htmx.process(div); - - div.click(); - this.server.respond(); - div.innerHTML.should.equal("delete"); - }) - - it('onLoad is called... onLoad', function(){ - // also tests on/off - this.server.respondWith("GET", "/test", "
    ") - var helper = htmx.onLoad(function (elt) { - elt.setAttribute("foo", "bar"); - }); - - try { - var div = make("
    "); - div.click(); - this.server.respond(); - byId("d1").getAttribute("foo").should.equal("bar"); - htmx.off("htmx:load", helper); - } catch (error) { - // Clean up the event if the test fails, then throw it again - htmx.off("htmx:load", helper); - throw error; - } - }); - - it('triggers properly', function () { - var div = make("
    "); - var myEventCalled = false; - var detailStr = ""; - htmx.on("myEvent", function(evt){ - myEventCalled = true; - detailStr = evt.detail.str; - }) - htmx.trigger(div, "myEvent", {str:"foo"}) - - myEventCalled.should.equal(true); - detailStr.should.equal("foo"); - }); - - it('triggers properly w/ selector', function () { - var div = make("
    "); - var myEventCalled = false; - var detailStr = ""; - htmx.on("myEvent", function(evt){ - myEventCalled = true; - detailStr = evt.detail.str; - }) - htmx.trigger("#div1", "myEvent", {str:"foo"}) - - myEventCalled.should.equal(true); - detailStr.should.equal("foo"); - }); - - it('triggers with no details properly', function () { - var div = make("
    "); - var myEventCalled = false; - htmx.on("myEvent", function(evt){ - myEventCalled = true; - }) - htmx.trigger(div, "myEvent") - myEventCalled.should.equal(true); - }); - -}) diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/events.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/events.js deleted file mode 100644 index 7c1c1596340..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/events.js +++ /dev/null @@ -1,692 +0,0 @@ -describe("Core htmx Events", function() { - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it("htmx:load fires properly", function () { - var called = false; - var handler = htmx.on("htmx:load", function (evt) { - called = true; - }); - try { - this.server.respondWith("GET", "/test", ""); - this.server.respondWith("GET", "/test", "
    "); - var div = make("
    "); - div.click(); - this.server.respond(); - should.equal(called, true); - } finally { - htmx.off("htmx:load", handler); - } - }); - - it("htmx:configRequest allows attribute addition", function () { - var handler = htmx.on("htmx:configRequest", function (evt) { - evt.detail.parameters['param'] = "true"; - }); - try { - var param = null; - this.server.respondWith("POST", "/test", function (xhr) { - param = getParameters(xhr)['param']; - xhr.respond(200, {}, ""); - }); - var div = make("
    "); - div.click(); - this.server.respond(); - param.should.equal("true"); - } finally { - htmx.off("htmx:configRequest", handler); - } - }); - - it("htmx:configRequest is also dispatched in kebab-case", function () { - var handler = htmx.on("htmx:config-request", function (evt) { - evt.detail.parameters['param'] = "true"; - }); - try { - var param = null; - this.server.respondWith("POST", "/test", function (xhr) { - param = getParameters(xhr)['param']; - xhr.respond(200, {}, ""); - }); - var div = make("
    "); - div.click(); - this.server.respond(); - param.should.equal("true"); - } finally { - htmx.off("htmx:config-request", handler); - } - }); - - it("events are only dispatched once if kebab and camel case match", function () { - var invoked = 0; - var handler = htmx.on("custom", function () { - invoked = invoked + 1 - }); - try { - var div = make("
    "); - htmx.trigger(div, "custom"); - invoked.should.equal(1); - } finally { - htmx.off("custom", handler); - } - }); - - it("htmx:configRequest allows attribute removal", function () { - var param = "foo"; - var handler = htmx.on("htmx:configRequest", function (evt) { - delete evt.detail.parameters['param']; - }); - try { - this.server.respondWith("POST", "/test", function (xhr) { - param = getParameters(xhr)['param']; - xhr.respond(200, {}, ""); - }); - var div = make("
    "); - div.click(); - this.server.respond(); - should.equal(param, undefined); - } finally { - htmx.off("htmx:configRequest", handler); - } - }); - - it("htmx:configRequest allows header tweaking", function () { - var header = "foo"; - var handler = htmx.on("htmx:configRequest", function (evt) { - evt.detail.headers['X-My-Header'] = "bar"; - }); - try { - this.server.respondWith("POST", "/test", function (xhr) { - header = xhr.requestHeaders['X-My-Header']; - xhr.respond(200, {}, ""); - }); - var div = make("
    "); - div.click(); - this.server.respond(); - should.equal(header, "bar"); - } finally { - htmx.off("htmx:configRequest", handler); - } - }); - - it("htmx:configRequest on form gives access to submit event", function () { - var skip = false - var submitterId; - var handler = htmx.on("htmx:configRequest", function (evt) { - // submitter may be null, but undefined means the browser doesn't support it - if (typeof evt.detail.triggeringEvent.submitter === "undefined") { - skip = true - return - } - evt.detail.headers['X-Submitter-Id'] = evt.detail.triggeringEvent.submitter.id; - }); - try { - this.server.respondWith("POST", "/test", function (xhr) { - submitterId = xhr.requestHeaders['X-Submitter-Id'] - xhr.respond(200, {}, ""); - }); - make('
    '); - var btn = byId('b1'); - btn.click(); - this.server.respond(); - if (skip) { - this._runnable.title += " - Skipped as IE11 doesn't support submitter" - this.skip() - } - should.equal(submitterId, "b1") - } finally { - htmx.off("htmx:configRequest", handler); - } - }); - - it("htmx:afterSwap is called when replacing outerHTML", function () { - var called = false; - var handler = htmx.on("htmx:afterSwap", function (evt) { - called = true; - }); - try { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, ""); - }); - var div = make(""); - div.click(); - this.server.respond(); - should.equal(called, true); - } finally { - htmx.off("htmx:afterSwap", handler); - } - }); - - it("htmx:oobBeforeSwap is called before swap", function () { - var called = false; - var handler = htmx.on("htmx:oobBeforeSwap", function (evt) { - called = true; - }); - try { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, "
    Baz
    "); - }); - var oob = make('
    Blip
    '); - var div = make(""); - div.click(); - this.server.respond(); - byId("d1").innerHTML.should.equal("Baz"); - should.equal(called, true); - } finally { - htmx.off("htmx:oobBeforeSwap", handler); - } - }); - - it("htmx:oobBeforeSwap can abort a swap", function () { - var called = false; - var handler = htmx.on("htmx:oobBeforeSwap", function (evt) { - called = true; - evt.preventDefault(); - }); - try { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, "
    Baz
    "); - }); - var oob = make('
    Blip
    '); - var div = make(""); - div.click(); - this.server.respond(); - byId("d1").innerHTML.should.equal("Blip"); - should.equal(called, true); - } finally { - htmx.off("htmx:oobBeforeSwap", handler); - } - }); - - - it("htmx:oobBeforeSwap is not called on an oob miss", function () { - var called = false; - var handler = htmx.on("htmx:oobBeforeSwap", function (evt) { - called = true; - }); - try { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, "
    Baz
    "); - }); - var div = make(""); - div.click(); - this.server.respond(); - should.equal(called, false); - } finally { - htmx.off("htmx:oobBeforeSwap", handler); - } - }); - - it("htmx:oobAfterSwap is called after swap", function () { - var called = false; - var handler = htmx.on("htmx:oobAfterSwap", function (evt) { - called = true; - }); - try { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, "
    Baz
    "); - }); - var oob = make('
    Blip
    '); - var div = make(""); - div.click(); - this.server.respond(); - byId("d1").innerHTML.should.equal("Baz"); - should.equal(called, true); - } finally { - htmx.off("htmx:oobAfterSwap", handler); - } - }); - - it("htmx:oobAfterSwap is not called on an oob miss", function () { - var called = false; - var handler = htmx.on("htmx:oobAfterSwap", function (evt) { - called = true; - }); - try { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, "
    Baz
    "); - }); - var div = make(""); - div.click(); - this.server.respond(); - should.equal(called, false); - } finally { - htmx.off("htmx:oobAfterSwap", handler); - } - }); - - it("htmx:afterSettle is called once when replacing outerHTML", function () { - var called = 0; - var handler = htmx.on("htmx:afterSettle", function (evt) { - called++; - }); - try { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, ""); - }); - var div = make(""); - div.click(); - this.server.respond(); - should.equal(called, 1); - } finally { - htmx.off("htmx:afterSettle", handler); - } - }); - - it("htmx:afterSettle is called once when replacing outerHTML with whitespace", function () { - var called = 0; - var handler = htmx.on("htmx:afterSettle", function (evt) { - called++; - }); - try { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, "\n"); - }); - var div = make(""); - div.click(); - this.server.respond(); - should.equal(called, 1); - } finally { - htmx.off("htmx:afterSettle", handler); - } - }); - - it("htmx:afterSettle is called twice when replacing outerHTML with whitespace separated elements", function () { - var called = 0; - var handler = htmx.on("htmx:afterSettle", function (evt) { - called++; - }); - try { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, "\n Foo"); - }); - var div = make(""); - div.click(); - this.server.respond(); - should.equal(called, 2); - } finally { - htmx.off("htmx:afterSettle", handler); - } - }); - - it("htmx:afterSettle is called multiple times when doing OOB outerHTML swaps", function () { - var called = 0; - var handler = htmx.on("htmx:afterSettle", function (evt) { - called++; - }); - try { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, "\n
    t1
    t2
    "); - }); - var div = make("
    "); - var button = byId("button") - button.click(); - this.server.respond(); - should.equal(called, 3); - } finally { - htmx.off("htmx:afterSettle", handler); - } - }); - - it("htmx:afterRequest is called after a successful request", function () { - var called = false; - var handler = htmx.on("htmx:afterRequest", function (evt) { - called = true; - }); - try { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, ""); - }); - var div = make(""); - div.click(); - this.server.respond(); - should.equal(called, true); - } finally { - htmx.off("htmx:afterRequest", handler); - } - }); - - it("htmx:afterOnLoad is called after a successful request", function () { - var called = false; - var handler = htmx.on("htmx:afterOnLoad", function (evt) { - called = true; - }); - try { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, ""); - }); - var div = make(""); - div.click(); - this.server.respond(); - should.equal(called, true); - } finally { - htmx.off("htmx:afterOnLoad", handler); - } - }); - - it("htmx:afterRequest is called after a failed request", function () { - var called = false; - var handler = htmx.on("htmx:afterRequest", function (evt) { - called = true; - }); - try { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(500, {}, ""); - }); - var div = make(""); - div.click(); - this.server.respond(); - should.equal(called, true); - } finally { - htmx.off("htmx:afterRequest", handler); - } - }); - - it("htmx:sendError is called after a failed request", function (done) { - if (IsIE11()) { - // IE will throw an exception on xhr.open with the URL below, xhr.send won't even be called - this._runnable.title += " - Skipped on IE11 as xhr.send won't even be called with a file URL" - this.skip() - return - } - var called = false; - var handler = htmx.on("htmx:sendError", function (evt) { - called = true; - }); - this.server.restore(); // turn off server mock so connection doesn't work - var div = make(""); - div.click(); - setTimeout(function () { - htmx.off("htmx:sendError", handler); - should.equal(called, true); - done(); - }, 30); - }); - - it("htmx:afterRequest is called when replacing outerHTML", function () { - var called = false; - var handler = htmx.on("htmx:afterRequest", function (evt) { - called = true; - }); - try { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, ""); - }); - var div = make(""); - div.click(); - this.server.respond(); - should.equal(called, true); - } finally { - htmx.off("htmx:afterRequest", handler); - } - }); - - it("htmx:afterOnLoad is called when replacing outerHTML", function () { - var called = false; - var handler = htmx.on("htmx:afterOnLoad", function (evt) { - called = true; - }); - try { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, ""); - }); - var div = make(""); - div.click(); - this.server.respond(); - should.equal(called, true); - } finally { - htmx.off("htmx:afterOnLoad", handler); - } - }); - - it("htmx:beforeProcessNode is called when replacing outerHTML", function () { - var called = false; - var handler = htmx.on("htmx:beforeProcessNode", function (evt) { - called = true; - }); - try { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, ""); - }); - var div = make(""); - div.click(); - this.server.respond(); - should.equal(called, true); - } finally { - htmx.off("htmx:beforeProcessNode", handler); - } - }); - - it("htmx:beforeProcessNode allows htmx attribute tweaking", function () { - var called = false; - var handler = htmx.on("htmx:beforeProcessNode", function (evt) { - evt.target.setAttribute("hx-post", "/success") - called = true; - }); - try { - this.server.respondWith("POST", "/success", function (xhr) { - xhr.respond(200, {}, ""); - }); - var div = make(""); - div.click(); - this.server.respond(); - should.equal(called, true); - } finally { - htmx.off("htmx:beforeProcessNode", handler); - } - }); - - it("htmx:afterProcessNode is called after replacing outerHTML", function () { - var called = false; - var handler = htmx.on("htmx:afterProcessNode", function (evt) { - called = true; - }); - try { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, ""); - }); - var div = make(""); - div.click(); - this.server.respond(); - should.equal(called, true); - } finally { - htmx.off("htmx:afterProcessNode", handler); - } - }); - - it("htmx:afterRequest is called when targeting a parent div", function () { - var called = false; - var handler = htmx.on("htmx:afterRequest", function (evt) { - called = true; - }); - try { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, ""); - }); - var div = make("
    "); - var button = byId('b1'); - button.click(); - this.server.respond(); - should.equal(called, true); - } finally { - htmx.off("htmx:afterRequest", handler); - } - }); - - it("adding an error in htmx:configRequest stops the request", function () { - try { - var handler = htmx.on("htmx:configRequest", function (evt) { - evt.detail.errors.push("An error"); - }); - var request = false; - this.server.respondWith("POST", "/test", function (xhr) { - request = true; - xhr.respond(200, {}, ""); - }); - var div = make(""); - div.click(); - this.server.respond(); - should.equal(request, false); - } finally { - htmx.off("htmx:configRequest", handler); - } - }); - - it("preventDefault() in htmx:configRequest stops the request", function () { - try { - var handler = htmx.on("htmx:configRequest", function (evt) { - evt.preventDefault(); - }); - var request = false; - this.server.respondWith("POST", "/test", function (xhr) { - request = true; - xhr.respond(200, {}, ""); - }); - var div = make(""); - div.click(); - this.server.respond(); - should.equal(request, false); - } finally { - htmx.off("htmx:configRequest", handler); - } - }); - - it("preventDefault() in the htmx:beforeRequest event cancels the request", function () { - try { - var handler = htmx.on("htmx:beforeRequest", function (evt) { - evt.preventDefault(); - }); - var request = false; - this.server.respondWith("POST", "/test", function (xhr) { - request = true; - xhr.respond(200, {}, ""); - }); - var div = make(""); - div.click(); - this.server.respond(); - should.equal(request, false); - } finally { - htmx.off("htmx:beforeRequest", handler); - } - }); - - it("preventDefault() in the htmx:beforeOnLoad event cancels the swap", function () { - try { - var handler = htmx.on("htmx:beforeOnLoad", function (evt) { - evt.preventDefault(); - }); - var request = false; - this.server.respondWith("POST", "/test", function (xhr) { - request = true; - xhr.respond(200, {}, "Bar"); - }); - var div = make(""); - div.click(); - this.server.respond(); - should.equal(request, true); - div.innerText.should.equal("Foo"); - } finally { - htmx.off("htmx:beforeOnLoad", handler); - } - }); - - it("htmx:afterRequest event contains 'successful' and 'failed' properties indicating success after successful request", function () { - var successful = false; - var failed = true; - var handler = htmx.on("htmx:afterRequest", function (evt) { - successful = evt.detail.successful; - failed = evt.detail.failed; - }); - try { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(200, {}, ""); - }); - var div = make(""); - div.click(); - this.server.respond(); - should.equal(successful, true); - should.equal(failed, false); - } finally { - htmx.off("htmx:afterRequest", handler); - } - }); - - it("htmx:afterRequest event contains 'successful' and 'failed' properties indicating failure after failed request", function () { - var successful = true; - var failed = false; - var handler = htmx.on("htmx:afterRequest", function (evt) { - successful = evt.detail.successful; - failed = evt.detail.failed; - }); - try { - this.server.respondWith("POST", "/test", function (xhr) { - xhr.respond(500, {}, ""); - }); - var div = make(""); - div.click(); - this.server.respond(); - should.equal(successful, false); - should.equal(failed, true); - } finally { - htmx.off("htmx:afterRequest", handler); - } - }); - - - it("htmx:confirm can cancel request", function () { - var allow = false; - var handler = htmx.on("htmx:confirm", function (evt) { - evt.preventDefault(); - if (allow) { - evt.detail.issueRequest(); - } - }); - - try { - this.server.respondWith("GET", "/test", "updated"); - var div = make("
    "); - div.click(); - this.server.respond(); - div.innerHTML.should.equal(""); - allow = true; - div.click(); - this.server.respond(); - div.innerHTML.should.equal("updated"); - } finally { - htmx.off("htmx:confirm", handler); - } - }); - - it("has updated target available when target set via htmx:beforeSwap", function () { - - var targetWasUpdatedInAfterSwapHandler = false; - - var beforeSwapHandler = htmx.on("htmx:beforeSwap", function (evt) { - console.log("beforeSwap", evt.detail.target, byId('d2')); - evt.detail.target = byId('d2'); - }); - var afterSwapHandler = htmx.on("htmx:afterSwap", function (evt) { - console.log("afterSwap", evt.detail.target, byId('d2')); - targetWasUpdatedInAfterSwapHandler = evt.detail.target === byId('d2'); - }); - - try { - this.server.respondWith("GET", "/test", "updated"); - make("
    "); - var div = byId('d0'); - div.click(); - this.server.respond(); - targetWasUpdatedInAfterSwapHandler.should.equal(true); - } finally { - htmx.off("htmx:beforeSwap", beforeSwapHandler); - htmx.off("htmx:afterSwap", afterSwapHandler); - } - }); - -}); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/extensions.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/extensions.js deleted file mode 100644 index f2d3ed2a9a5..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/extensions.js +++ /dev/null @@ -1,47 +0,0 @@ -describe('Core htmx extension tests', function() { - beforeEach(function() { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function() { - this.server.restore(); - clearWorkArea(); - }); - - it('should support event cancellation by returning false', function() { - htmx.defineExtension('ext-prevent-request', { - onEvent: function(name, evt) { - if (name === 'htmx:beforeRequest') { - return false; - } - } - }); - - this.server.respondWith('GET', '/test', 'clicked!'); - var div = make('
    Click Me!
    ') - div.click(); - this.server.respond(); - div.innerHTML.should.equal('Click Me!'); - }); - - it('should support event cancellation with preventDefault', function() { - htmx.defineExtension('ext-prevent-request', { - onEvent: function(name, evt) { - if (name === 'htmx:beforeRequest') { - evt.preventDefault(); - if (IsIE11()) { - // IE11 doesn't set defaultPrevented to true on custom events it seems, so use a - // return false instead to cancel the event - return false - } - } - } - }); - - this.server.respondWith('GET', '/test', 'clicked!'); - var div = make('
    Click Me!
    ') - div.click(); - this.server.respond(); - div.innerHTML.should.equal('Click Me!'); - }); -}); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/headers.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/headers.js deleted file mode 100644 index 7e127ece104..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/headers.js +++ /dev/null @@ -1,378 +0,0 @@ -describe("Core htmx AJAX headers", function () { - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it("should include the HX-Request header", function () { - this.server.respondWith("GET", "/test", function (xhr) { - xhr.requestHeaders['HX-Request'].should.be.equal('true'); - xhr.respond(200, {}, ""); - }); - var div = make('
    '); - div.click(); - this.server.respond(); - }) - - it("should include the HX-Trigger header", function () { - this.server.respondWith("GET", "/test", function (xhr) { - xhr.requestHeaders['HX-Trigger'].should.equal('d1'); - xhr.respond(200, {}, ""); - }); - var div = make('
    '); - div.click(); - this.server.respond(); - }) - - it("should include the HX-Trigger-Name header", function () { - this.server.respondWith("GET", "/test", function (xhr) { - xhr.requestHeaders['HX-Trigger-Name'].should.equal('n1'); - xhr.respond(200, {}, ""); - }); - var div = make(''); - div.click(); - this.server.respond(); - }) - - it("should include the HX-Target header", function () { - this.server.respondWith("GET", "/test", function (xhr) { - xhr.requestHeaders['HX-Target'].should.equal('d1'); - xhr.respond(200, {}, ""); - }); - var div = make('
    '); - div.click(); - this.server.respond(); - }) - - it("should handle simple string HX-Trigger response header properly", function () { - this.server.respondWith("GET", "/test", [200, {"HX-Trigger": "foo"}, ""]); - - var div = make('
    '); - var invokedEvent = false; - div.addEventListener("foo", function (evt) { - invokedEvent = true; - }); - div.click(); - this.server.respond(); - invokedEvent.should.equal(true); - }) - - it("should handle dot path HX-Trigger response header properly", function () { - this.server.respondWith("GET", "/test", [200, {"HX-Trigger": "foo.bar"}, ""]); - - var div = make('
    '); - var invokedEvent = false; - div.addEventListener("foo.bar", function (evt) { - invokedEvent = true; - }); - div.click(); - this.server.respond(); - invokedEvent.should.equal(true); - }) - - it("should handle simple string HX-Trigger response header in different case properly", function () { - this.server.respondWith("GET", "/test", [200, {"hx-trigger": "foo"}, ""]); - - var div = make('
    '); - var invokedEvent = false; - div.addEventListener("foo", function (evt) { - invokedEvent = true; - }); - div.click(); - this.server.respond(); - invokedEvent.should.equal(true); - }) - - it("should handle a namespaced HX-Trigger response header properly", function () { - this.server.respondWith("GET", "/test", [200, {"HX-Trigger": "namespace:foo"}, ""]); - - var div = make('
    '); - var invokedEvent = false; - div.addEventListener("namespace:foo", function (evt) { - invokedEvent = true; - }); - div.click(); - this.server.respond(); - invokedEvent.should.equal(true); - }) - - it("should handle basic JSON HX-Trigger response header properly", function () { - this.server.respondWith("GET", "/test", [200, {"HX-Trigger": "{\"foo\":null}"}, ""]); - - var div = make('
    '); - var invokedEvent = false; - div.addEventListener("foo", function (evt) { - invokedEvent = true; - should.equal(null, evt.detail.value); - evt.detail.elt.should.equal(div); - }); - div.click(); - this.server.respond(); - invokedEvent.should.equal(true); - }) - - it("should handle JSON with array arg HX-Trigger response header properly", function () { - this.server.respondWith("GET", "/test", [200, {"HX-Trigger": "{\"foo\":[1, 2, 3]}"}, ""]); - - var div = make('
    '); - var invokedEvent = false; - div.addEventListener("foo", function (evt) { - invokedEvent = true; - evt.detail.elt.should.equal(div); - evt.detail.value.should.deep.equal([1, 2, 3]); - }); - div.click(); - this.server.respond(); - invokedEvent.should.equal(true); - }) - - it("should handle JSON with array arg HX-Trigger response header properly", function () { - this.server.respondWith("GET", "/test", [200, {"HX-Trigger": "{\"foo\":{\"a\":1, \"b\":2}}"}, ""]); - - var div = make('
    '); - var invokedEvent = false; - div.addEventListener("foo", function (evt) { - invokedEvent = true; - evt.detail.elt.should.equal(div); - evt.detail.a.should.equal(1); - evt.detail.b.should.equal(2); - }); - div.click(); - this.server.respond(); - invokedEvent.should.equal(true); - }) - - it("should survive malformed JSON in HX-Trigger response header", function () { - this.server.respondWith("GET", "/test", [200, {"HX-Trigger": "{not: valid}"}, ""]); - - var div = make('
    '); - div.click(); - this.server.respond(); - }) - - it("should handle simple string HX-Trigger response header properly w/ outerHTML swap", function () { - this.server.respondWith("GET", "/test", [200, {"HX-Trigger": "foo"}, ""]); - - var div = make('
    '); - var invokedEvent = false; - var handler = htmx.on('foo', function (evt) { - invokedEvent = true; - }); - div.click(); - this.server.respond(); - invokedEvent.should.equal(true); - htmx.off('foo', handler); - }) - - it("should handle simple comma separated list HX-Trigger response header properly", function () { - this.server.respondWith("GET", "/test", [200, {"HX-Trigger": "foo, bar"}, ""]); - - var div = make('
    '); - var invokedEventFoo = false; - var invokedEventBar = false; - div.addEventListener("foo", function (evt) { - invokedEventFoo = true; - }); - div.addEventListener("bar", function (evt) { - invokedEventBar = true; - }); - div.click(); - this.server.respond(); - invokedEventFoo.should.equal(true); - invokedEventBar.should.equal(true); - }) - - it("should handle simple comma separated list without space HX-Trigger response header properly", function () { - this.server.respondWith("GET", "/test", [200, {"HX-Trigger": "foo,bar"}, ""]); - - var div = make('
    '); - var invokedEventFoo = false; - var invokedEventBar = false; - div.addEventListener("foo", function (evt) { - invokedEventFoo = true; - }); - div.addEventListener("bar", function (evt) { - invokedEventBar = true; - }); - div.click(); - this.server.respond(); - invokedEventFoo.should.equal(true); - invokedEventBar.should.equal(true); - }) - - it("should handle dot path in comma separated list HX-Trigger response header properly", function () { - this.server.respondWith("GET", "/test", [200, {"HX-Trigger": "foo.bar,bar.baz"}, ""]); - - var div = make('
    '); - var invokedEventFoo = false; - var invokedEventBar = false; - div.addEventListener("foo.bar", function (evt) { - invokedEventFoo = true; - }); - div.addEventListener("bar.baz", function (evt) { - invokedEventBar = true; - }); - div.click(); - this.server.respond(); - invokedEventFoo.should.equal(true); - invokedEventBar.should.equal(true); - }) - - it("should handle a namespaced comma separated list HX-Trigger response header properly", function () { - this.server.respondWith("GET", "/test", [200, {"HX-Trigger": "namespace:foo,bar"}, ""]); - - var div = make('
    '); - var invokedEventFoo = false; - var invokedEventBar = false; - div.addEventListener("namespace:foo", function (evt) { - invokedEventFoo = true; - }); - div.addEventListener("bar", function (evt) { - invokedEventBar = true; - }); - div.click(); - this.server.respond(); - invokedEventFoo.should.equal(true); - invokedEventBar.should.equal(true); - }) - - it("should handle HX-Retarget", function () { - this.server.respondWith("GET", "/test", [200, {"HX-Retarget": "#d2"}, "Result"]); - - var div1 = make('
    '); - var div2 = make('
    '); - div1.click(); - this.server.respond(); - div1.innerHTML.should.equal(""); - div2.innerHTML.should.equal("Result"); - }) - - it("should handle HX-Reswap", function () { - this.server.respondWith("GET", "/test", [200, {"HX-Reswap": "innerHTML"}, "Result"]); - - var div1 = make('
    '); - div1.click(); - this.server.respond(); - div1.innerHTML.should.equal("Result"); - }) - - it("should handle HX-Reselect", function () { - this.server.respondWith("GET", "/test", [200, {"HX-Reselect": "#d2"}, "
    foo
    bar
    "]); - - var div = make('
    '); - div.click(); - this.server.respond(); - - div.innerHTML.should.equal('
    bar
    '); - }); - - it("should handle simple string HX-Trigger-After-Swap response header properly w/ outerHTML swap", function () { - this.server.respondWith("GET", "/test", [200, {"HX-Trigger-After-Swap": "foo"}, ""]); - - var div = make('
    '); - var invokedEvent = false; - var handler = htmx.on('foo', function (evt) { - invokedEvent = true; - }); - div.click(); - this.server.respond(); - invokedEvent.should.equal(true); - htmx.off('foo', handler); - }) - - it("should handle simple comma separated list HX-Trigger-After-Swap response header properly w/ outerHTML swap", function () { - this.server.respondWith("GET", "/test", [200, {"HX-Trigger-After-Swap": "foo, bar"}, ""]); - - var div = make('
    '); - var invokedEventFoo = false; - var invokedEventBar = false; - var handlerFoo = htmx.on('foo', function (evt) { - invokedEventFoo = true; - }); - var handlerBar = htmx.on('bar', function (evt) { - invokedEventBar = true; - }); - div.click(); - this.server.respond(); - invokedEventFoo.should.equal(true); - invokedEventBar.should.equal(true); - htmx.off('foo', handlerFoo); - htmx.off('bar', handlerBar); - }) - - it("should handle simple string HX-Trigger-After-Settle response header properly w/ outerHTML swap", function () { - this.server.respondWith("GET", "/test", [200, {"HX-Trigger-After-Settle": "foo"}, ""]); - - var div = make('
    '); - var invokedEvent = false; - var handler = htmx.on('foo', function (evt) { - invokedEvent = true; - }); - div.click(); - this.server.respond(); - invokedEvent.should.equal(true); - htmx.off('foo', handler); - }) - - it("should handle simple comma separated list HX-Trigger-After-Settle response header properly w/ outerHTML swap", function () { - this.server.respondWith("GET", "/test", [200, {"HX-Trigger-After-Settle": "foo, bar"}, ""]); - - var div = make('
    '); - var invokedEventFoo = false; - var invokedEventBar = false; - var handlerFoo = htmx.on('foo', function (evt) { - invokedEventFoo = true; - }); - var handlerBar = htmx.on('bar', function (evt) { - invokedEventBar = true; - }); - div.click(); - this.server.respond(); - invokedEventFoo.should.equal(true); - invokedEventBar.should.equal(true); - htmx.off('foo', handlerFoo); - htmx.off('bar', handlerBar); - }) - - - it("should change body content on HX-Location", function () { - this.server.respondWith("GET", "/test", [200, {"HX-Location": '{"path":"/test2", "target":"#testdiv"}'}, ""]); - this.server.respondWith("GET", "/test2", [200, {}, "
    Yay! Welcome
    "]); - var div = make('
    '); - div.click(); - this.server.respond(); - this.server.respond(); - div.innerHTML.should.equal('
    Yay! Welcome
    '); - }) - - it('request to restore history should include the HX-Request header', function () { - this.server.respondWith('GET', '/test', function (xhr) { - xhr.requestHeaders['HX-Request'].should.be.equal('true'); - xhr.respond(200, {}, ''); - }); - htmx._('loadHistoryFromServer')('/test'); - this.server.respond(); - }); - - it('request to restore history should include the HX-History-Restore-Request header', function () { - this.server.respondWith('GET', '/test', function (xhr) { - xhr.requestHeaders['HX-History-Restore-Request'].should.be.equal('true'); - xhr.respond(200, {}, ''); - }); - htmx._('loadHistoryFromServer')('/test'); - this.server.respond(); - }); - - it('request to restore history should include the HX-Current-URL header', function () { - this.server.respondWith('GET', '/test', function (xhr) { - chai.assert(typeof xhr.requestHeaders['HX-Current-URL'] !== 'undefined', 'HX-Current-URL should not be undefined'); - xhr.respond(200, {}, ''); - }); - htmx._('loadHistoryFromServer')('/test'); - this.server.respond(); - }); -}); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/internals.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/internals.js deleted file mode 100644 index 3d689293ec2..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/internals.js +++ /dev/null @@ -1,149 +0,0 @@ -describe("Core htmx internals Tests", function() { - - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it("makeFragment works with janky stuff", function(){ - htmx._("makeFragment")("").tagName.should.equal("BODY"); - htmx._("makeFragment")("").tagName.should.equal("BODY"); - - //NB - the tag name should be the *parent* element hosting the HTML since we use the fragment children - // for the swap - htmx._("makeFragment")("").tagName.should.equal("TR"); - htmx._("makeFragment")("").tagName.should.equal("TABLE"); - htmx._("makeFragment")("").tagName.should.equal("COLGROUP"); - htmx._("makeFragment")("").tagName.should.equal("TBODY"); - }) - - it("makeFragment works with template wrapping", function(){ - if (!supportsTemplates()) { - this._runnable.title += " - Skipped as IE11 doesn't support templates" - this.skip() - return - } - try { - htmx._("makeFragment")("").children.length.should.equal(0); - htmx._("makeFragment")("").children.length.should.equal(0); - - var fragment = htmx._("makeFragment")(""); - fragment.firstElementChild.tagName.should.equal("TD"); - - fragment = htmx._("makeFragment")(""); - fragment.firstElementChild.tagName.should.equal("THEAD"); - - fragment = htmx._("makeFragment")(""); - fragment.firstElementChild.tagName.should.equal("COL"); - - fragment = htmx._("makeFragment")(""); - fragment.firstElementChild.tagName.should.equal("TR"); - - } finally { - htmx.config.useTemplateFragments = false; - } - }) - - - it("makeFragment works with template wrapping and funky combos", function(){ - if (!supportsTemplates()) { - this._runnable.title += " - Skipped as IE11 doesn't support templates" - this.skip() - return - } - htmx.config.useTemplateFragments = true; - try { - var fragment = htmx._("makeFragment")("
    "); - fragment.children[0].tagName.should.equal("TD"); - fragment.children[1].tagName.should.equal("DIV"); - } finally { - htmx.config.useTemplateFragments = false; - } - }) - - it("set header works with non-ASCII values", function(){ - var xhr = new XMLHttpRequest(); - xhr.open("GET", "/dummy"); - htmx._("safelySetHeaderValue")(xhr, "Example", "привет"); - // unfortunately I can't test the value :/ - // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest - }) - - it("handles parseInterval correctly", function() { - chai.expect(htmx.parseInterval("1ms")).to.be.equal(1); - chai.expect(htmx.parseInterval("300ms")).to.be.equal(300); - chai.expect(htmx.parseInterval("1s")).to.be.equal(1000); - chai.expect(htmx.parseInterval("1.5s")).to.be.equal(1500); - chai.expect(htmx.parseInterval("2s")).to.be.equal(2000); - chai.expect(htmx.parseInterval("0ms")).to.be.equal(0); - chai.expect(htmx.parseInterval("0s")).to.be.equal(0); - chai.expect(htmx.parseInterval("0m")).to.be.equal(0); - chai.expect(htmx.parseInterval("0")).to.be.equal(0); - chai.expect(htmx.parseInterval("5")).to.be.equal(5); - - chai.expect(htmx.parseInterval(null)).to.be.undefined - chai.expect(htmx.parseInterval("")).to.be.undefined - chai.expect(htmx.parseInterval("undefined")).to.be.undefined - chai.expect(htmx.parseInterval("true")).to.be.undefined - chai.expect(htmx.parseInterval("false")).to.be.undefined - }) - - it("tokenizes correctly", function() { - chai.expect(htmx._("tokenizeString")("a,")).to.be.deep.equal(['a', ',']); - chai.expect(htmx._("tokenizeString")("aa,")).to.be.deep.equal(['aa', ',']); - chai.expect(htmx._("tokenizeString")("aa,aa")).to.be.deep.equal(['aa', ',', 'aa']); - chai.expect(htmx._("tokenizeString")("aa.aa")).to.be.deep.equal(['aa', '.', 'aa']); - }) - - it("tags respond correctly to shouldCancel", function() { - var anchorThatShouldCancel = make(""); - htmx._("shouldCancel")({type:'click'}, anchorThatShouldCancel).should.equal(true); - - var anchorThatShouldCancel = make(""); - htmx._("shouldCancel")({type:'click'}, anchorThatShouldCancel).should.equal(true); - - var anchorThatShouldNotCancel = make(""); - htmx._("shouldCancel")({type:'click'}, anchorThatShouldNotCancel).should.equal(false); - - var form = make("
    "); - htmx._("shouldCancel")({type:'submit'}, form).should.equal(true); - - var form = make("
    "); - var input = byId("i1"); - htmx._("shouldCancel")({type:'click'}, input).should.equal(true); - - var form = make("
    '); - var input = byId('i1'); - var button = byId('b1'); - // Listen for focusin on form as it'll bubble up from the button, and htmx binds on the form itself - form.addEventListener("focusin", function () { - var vals = htmx._('getInputValues')(form).values; - vals['foo'].should.equal('bar'); - vals['do'].should.equal('rey'); - vals['btn'].should.equal('bar'); - done(); - }); - button.focus(); - }) - - it('form includes last focused submit', function (done) { - var form = make('
    '); - var input = byId('i1'); - var button = byId('s1'); - // Listen for focusin on form as it'll bubble up from the button, and htmx binds on the form itself - form.addEventListener("focusin", function () { - var vals = htmx._('getInputValues')(form).values; - vals['foo'].should.equal('bar'); - vals['do'].should.equal('rey'); - vals['s1'].should.equal('bar'); - done(); - }); - button.focus(); - }) - - it('form does not include button when focus is lost', function () { - var form = make('
    '); - var input = byId('i1'); - var button = byId('s1'); - button.focus(); - input.focus(); - var vals = htmx._('getInputValues')(form).values; - vals['foo'].should.equal('bar'); - vals['do'].should.equal('rey'); - should.equal(vals['s1'], undefined); - }) - - it('form does not include button when focus is lost outside of form', function () { - var form = make('
    '); - var anchor = make(''); - var button = byId('s1'); - button.focus(); - anchor.focus(); - var vals = htmx._('getInputValues')(form).values; - vals['foo'].should.equal('bar'); - vals['do'].should.equal('rey'); - should.equal(vals['s1'], undefined); - }) - - it('form includes button name and value if button has nested elements when clicked', function () { - var form = make('
    '); - var nestedElt = byId('span1'); - nestedElt.click(); - var vals = htmx._('getInputValues')(form).values; - vals['do'].should.equal('rey'); - }) - - it('it puts GET params in the URL by default', function () { - this.server.respondWith("GET", "/test?i1=value", function (xhr) { - xhr.respond(200, {}, "Clicked!"); - }); - var form = make('
    '); - form.click(); - this.server.respond(); - form.innerHTML.should.equal("Clicked!"); - }); - - it('it puts GET params in the body if methodsThatUseUrlParams is empty', function () { - this.server.respondWith("GET", "/test", function (xhr) { - xhr.requestBody.should.equal("i1=value"); - xhr.respond(200, {}, "Clicked!"); - }); - var form = make('
    '); - - try { - htmx.config.methodsThatUseUrlParams = []; - form.click(); - this.server.respond(); - form.innerHTML.should.equal("Clicked!"); - } finally { - htmx.config.methodsThatUseUrlParams = ["get"]; - } - }); - - it('it puts DELETE params in the body by default', function () { - this.server.respondWith("DELETE", "/test", function (xhr) { - xhr.requestBody.should.equal("i1=value"); - xhr.respond(200, {}, "Clicked!"); - }); - var form = make('
    '); - form.click(); - this.server.respond(); - form.innerHTML.should.equal("Clicked!"); - }); - - it('it puts DELETE params in the URL if methodsThatUseUrlParams contains "delete"', function () { - this.server.respondWith("DELETE", "/test?i1=value", function (xhr) { - xhr.respond(200, {}, "Clicked!"); - }); - var form = make('
    '); - - try { - htmx.config.methodsThatUseUrlParams.push("delete") - form.click(); - this.server.respond(); - form.innerHTML.should.equal("Clicked!"); - } finally { - htmx.config.methodsThatUseUrlParams = ["get"]; - } - }); - - it('Input within disabled fieldset is excluded', function () { - var input = make('
    '); - var vals = htmx._('getInputValues')(input, "get").values; - vals['foo'].should.equal('bar'); - should.equal(vals["do"], undefined); - }) - -}); - diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/perf.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/perf.js deleted file mode 100644 index 2781da51954..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/perf.js +++ /dev/null @@ -1,69 +0,0 @@ -describe("Core htmx perf Tests", function() { - - var HTMX_HISTORY_CACHE_NAME = "htmx-history-cache"; - - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - localStorage.removeItem(HTMX_HISTORY_CACHE_NAME); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - localStorage.removeItem(HTMX_HISTORY_CACHE_NAME); - }); - - function stringRepeat(str, num) { - num = Number(num); - - var result = ''; - while (true) { - if (num & 1) { // (1) - result += str; - } - num >>>= 1; // (2) - if (num <= 0) break; - str += str; - } - - return result; - } - - - it("history implementation should be fast", function(){ - // create an entry with a large content string (256k) and see how fast we can write and read it - // to local storage as a single entry - var entry = {url: stringRepeat("x", 32), content:stringRepeat("x", 256*1024)} - var array = []; - for (var i = 0; i < 10; i++) { - array.push(entry); - } - var start = performance.now(); - var string = JSON.stringify(array); - localStorage.setItem(HTMX_HISTORY_CACHE_NAME, string); - var reReadString = localStorage.getItem(HTMX_HISTORY_CACHE_NAME); - var finalJson = JSON.parse(reReadString); - var end = performance.now(); - var timeInMs = end - start; - chai.assert(timeInMs < 300, "Should take less than 300ms on most platforms"); - }) - - it("history snapshot cleaning should be fast", function(){ - var size = 5 * 1024 // ~350K in size, about the size of CNN's body tag :p - if (IsIE11()) { - // So slow in IE11 it freezes the browser and blocks other tests, pretty annoying - size = 5 * 100 // Seriously this already takes ~1.5 SECOND to run, more simply makes it crash - } - var workArea = getWorkArea(); - var html = "
    Yay, really large HTML documents are fun!
    \n"; - html = stringRepeat(html, size); - workArea.insertAdjacentHTML("beforeend", html) - var start = performance.now(); - htmx._("cleanInnerHtmlForHistory")(workArea); - var end = performance.now(); - var timeInMs = end - start; - // change timeout for HtmlUnit builds chai.assert(timeInMs < 50, "Should take less than 50ms on most platforms"); - chai.assert(timeInMs < 200, "Should take less than 50ms on most platforms"); - }) - -}) \ No newline at end of file diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/regressions.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/regressions.js deleted file mode 100644 index 6a8c8e66940..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/regressions.js +++ /dev/null @@ -1,289 +0,0 @@ -describe("Core htmx Regression Tests", function(){ - - beforeEach(function() { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function() { - this.server.restore(); - clearWorkArea(); - }); - - it('SVGs process properly in IE11', function() - { - var btn = make('\n' + - '\n' + - '\n' + - '\n' + - '') - }); - - it ('Handles https://github.com/bigskysoftware/htmx/issues/4 properly', function() { - this.server.respondWith("GET", "/index2a.php", - "
    I came from message oob swap I should be second
    " + - "
    I came from a message2 oob swap I should be third but I am in the wrong spot
    " + - "I'm page2 content (non-swap) I should be first") - - var h1 = make("" + - "
    " + - "
    " + - "
    " + - "

    Kutty CLICK ME

    ") - h1.click(); - this.server.respond(); - htmx.find("#page2").innerHTML.should.equal("I'm page2 content (non-swap) I should be first") - htmx.find("#message").innerHTML.should.equal("I came from message oob swap I should be second") - htmx.find("#message2").innerHTML.should.equal("I came from a message2 oob swap I should be third but I am in the wrong spot") - }); - - it ('Handles https://github.com/bigskysoftware/htmx/issues/33 "empty values" properly', function() { - this.server.respondWith("POST", "/htmx.php", function (xhr) { - xhr.respond(200, {}, xhr.requestBody); - }); - - var form = make('
    \n' + - '\n' + - '\n' + - '
    ') - form.click(); - this.server.respond(); - form.innerHTML.should.equal("variable=") - }); - - it ('name=id doesnt cause an error', function(){ - this.server.respondWith("GET", "/test", "Foo
    ") - var div = make('
    Get It
    ') - div.click(); - this.server.respond(); - div.innerText.should.contain("Foo") - }); - - it ('empty id doesnt cause an error', function(){ - this.server.respondWith("GET", "/test", "Foo\n
    ") - var div = make('
    Get It
    ') - div.click(); - this.server.respond(); - div.innerText.should.contain("Foo") - }); - - it ('id with dot in value doesnt cause an error', function(){ - this.server.respondWith("GET", "/test", "Foo
    "); - var div = make('
    Get It
    '); - div.click(); - this.server.respond(); - div.innerText.should.contain("Foo"); - }); - - it ('@ symbol in attributes does not break requests', function(){ - this.server.respondWith("GET", "/test", "
    Foo
    "); - var div = make('
    Get It
    '); - div.click(); - this.server.respond(); - byId("d1").getAttribute('@foo').should.equal('bar'); - }); - - it ('@ symbol in attributes does not break attribute settling requests', function(){ - this.server.respondWith("GET", "/test", "
    Foo
    "); - var div = make('
    Foo
    '); - div.click(); - this.server.respond(); - byId("d1").getAttribute('@foo').should.equal('bar'); - }); - - it ('selected element with ID does not cause NPE when it disappears', function(){ - this.server.respondWith("GET", "/test", "
    Replaced
    "); - var input = make(''); - input.focus(); - input.click(); - this.server.respond(); - byId("d1").innerText.should.equal('Replaced'); - }); - - it('does not submit with a false condition on a form', function() { - this.server.respondWith("POST", "/test", "Submitted"); - var defaultPrevented = false; - htmx.on("click", function(evt) { - defaultPrevented = evt.defaultPrevented; - }) - var form = make('
    '); - form.click() - this.server.respond(); - defaultPrevented.should.equal(true); - }) - - it('two elements can listen for the same event on another element', function() { - this.server.respondWith("GET", "/test", "triggered"); - - make('
    ' + - '
    '); - - - var div1 = byId("d1"); - var div2 = byId("d2"); - - document.body.click(); - this.server.respond(); - - div2.innerHTML.should.equal("triggered"); - div1.innerHTML.should.equal("triggered"); - }) - - it('a form can reset based on the htmx:afterRequest event', function() { - if (IsIE11()) { - this._runnable.title += " - Skipped as hyperscript isn't IE11 compatible" - this.skip() - return - } - - this.server.respondWith("POST", "/test", "posted"); - - var form = make('
    ' + - ' ' + - ' ' + - '
    '); - htmx.trigger(form, "htmx:load"); // have to manually trigger the load event for non-AJAX dynamic content - - var div1 = byId("d1"); - var input = byId("i1"); - input.value = "foo"; - var submit = byId("s1"); - - input.value.should.equal("foo"); - submit.click(); - this.server.respond(); - - div1.innerHTML.should.equal("posted"); - input.value.should.equal(""); // form should be reset - }) - - it('supports image maps', function() { - this.server.respondWith("GET", "/test", "triggered"); - - make('
    ' + - '
    ' + - ' ' + - '' + - ' ' + - ' Computer' + - ' ' + - '
    '); - - var div1 = byId("d1"); - var area = document.getElementsByTagName('area')[0]; - - area.click(); - this.server.respond(); - - div1.innerHTML.should.equal("triggered"); - }) - - it("supports unset on hx-select", function(){ - this.server.respondWith("GET", "/test", "FooBar"); - make('
    \n' + - ' \n' + - '
    ') - var btn = byId("b1"); - btn.click() - this.server.respond(); - - btn.innerText.should.equal("FooBar"); - }) - - - it("can trigger swaps from fields that don't support setSelectionRange", function(){ - const template = '
    \n' + - '\n' + - '
    '; - - const response = '
    \n' + - '\n' + - '
    '; - this.server.respondWith("GET", "/test", response); - make(template); - var input = byId("id_email"); - // HTMX only attempts to restore the selection on inputs that have a current selection and are active. - // additionally we can't set the selection on email inputs (that's the whole bug) so start as a text input where you can set selection - // and replace with an email - input.focus(); - input.selectionStart = 3; - input.selectionEnd = 3; - input.click(); - this.server.respond(); - var input = byId("id_email"); - input.value.should.equal("supertest@test.com"); - }); - - it("script tags only execute once", function(done) { - window.i = 0; // set count to 0 - this.server.respondWith('GET', '/test', '') // increment the count by 1 - - // make a div w/ a short settle delay to make the problem more obvious - var div = make('
    '); - div.click(); - this.server.respond() - - setTimeout(function(){ - window.i.should.equal(1); - delete window.i; - done(); - }, 50) - }) - - it("script tags only execute once when nested", function(done) { - window.i = 0; // set count to 0 - this.server.respondWith('GET', '/test', '

    foo

    ') // increment the count by 1 - - // make a div w/ a short settle delay to make the problem more obvious - var div = make('
    '); - div.click(); - this.server.respond() - - setTimeout(function(){ - window.i.should.equal(1); - delete window.i; - done(); - }, 50) - }) - - it("script tags only execute once using templates", function(done) { - var oldUseTemplateFragmentsValue = htmx.config.useTemplateFragments - htmx.config.useTemplateFragments = true - - window.i = 0; // set count to 0 - this.server.respondWith('GET', '/test', '') // increment the count by 1 - - // make a div w/ a short settle delay to make the problem more obvious - var div = make('
    '); - div.click(); - this.server.respond() - - - setTimeout(function(){ - window.i.should.equal(1); - delete window.i; - htmx.config.useTemplateFragments = oldUseTemplateFragmentsValue - done(); - }, 50) - }) - - it("script tags only execute once when nested using templates", function(done) { - var oldUseTemplateFragmentsValue = htmx.config.useTemplateFragments - htmx.config.useTemplateFragments = true - - window.i = 0; // set count to 0 - this.server.respondWith('GET', '/test', '

    foo

    ') // increment the count by 1 - - // make a div w/ a short settle delay to make the problem more obvious - var div = make('
    '); - div.click(); - this.server.respond() - - setTimeout(function(){ - window.i.should.equal(1); - delete window.i; - htmx.config.useTemplateFragments = oldUseTemplateFragmentsValue - done(); - }, 50) - }) - -}); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/security.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/security.js deleted file mode 100644 index 95f17350209..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/security.js +++ /dev/null @@ -1,190 +0,0 @@ -describe("security options", function() { - - beforeEach(function() { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function() { - this.server.restore(); - clearWorkArea(); - }); - - it("can disable a single elt", function(){ - this.server.respondWith("GET", "/test", "Clicked!"); - - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Initial"); - }) - - it("can disable a parent elt", function(){ - this.server.respondWith("GET", "/test", "Clicked!"); - - var div = make('
    ') - var btn = byId("b1"); - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Initial"); - }) - - it("can disable a single elt dynamically", function(){ - this.server.respondWith("GET", "/test", "Clicked!"); - - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - - this.server.respondWith("GET", "/test", "Clicked a second time"); - - btn.setAttribute("hx-disable", "") - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - }) - - it("can disable a single elt dynamically & enable it back", function(){ - this.server.respondWith("GET", "/test", "Clicked!"); - - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - - this.server.respondWith("GET", "/test", "Clicked a second time"); - - btn.setAttribute("hx-disable", "") - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - - btn.removeAttribute("hx-disable") - htmx.process(btn) - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked a second time"); - }) - - it("can disable a single parent elt dynamically", function(){ - this.server.respondWith("GET", "/test", "Clicked!"); - - var div = make('
    ') - var btn = byId("b1"); - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - - this.server.respondWith("GET", "/test", "Clicked a second time"); - - div.setAttribute("hx-disable", "") - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - }) - - it("can disable a single parent elt dynamically & enable it back", function(){ - this.server.respondWith("GET", "/test", "Clicked!"); - - var div = make('
    ') - var btn = byId("b1"); - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - - this.server.respondWith("GET", "/test", "Clicked a second time"); - - div.setAttribute("hx-disable", "") - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - - div.removeAttribute("hx-disable") - htmx.process(div) - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked a second time"); - }) - - it("can make egress cross site requests when htmx.config.selfRequestsOnly is enabled", function(done){ - this.timeout(4000) - // should trigger send error, rather than reject - var listener = htmx.on("htmx:sendError", function (){ - htmx.off("htmx:sendError", listener); - done(); - }); - this.server.restore(); // use real xhrs - // will 404, but should respond - var btn = make('') - btn.click(); - }) - - it("can't make egress cross site requests when htmx.config.selfRequestsOnly is enabled", function(done){ - this.timeout(4000) - // should trigger send error, rather than reject - htmx.config.selfRequestsOnly = true; - var listener = htmx.on("htmx:invalidPath", function (){ - htmx.config.selfRequestsOnly = false; - htmx.off("htmx:invalidPath", listener); - done(); - }) - this.server.restore(); // use real xhrs - // will 404, but should respond - var btn = make('') - btn.click(); - }) - - it("can cancel egress request based on htmx:validateUrl event", function(done){ - this.timeout(4000) - // should trigger send error, rather than reject - var pathVerifier = htmx.on("htmx:validateUrl", function (evt){ - evt.preventDefault(); - htmx.off("htmx:validateUrl", pathVerifier); - }) - var listener = htmx.on("htmx:invalidPath", function (){ - htmx.off("htmx:invalidPath", listener); - done(); - }) - this.server.restore(); // use real xhrs - // will 404, but should respond - var btn = make('') - btn.click(); - }) - - it("can cancel egress request based on htmx:validateUrl event, sameHost is false", function(done){ - this.timeout(4000) - // should trigger send error, rather than reject - var pathVerifier = htmx.on("htmx:validateUrl", function (evt){ - if (evt.detail.sameHost === false) { - evt.preventDefault(); - } - htmx.off("htmx:validateUrl", pathVerifier); - }) - var listener = htmx.on("htmx:invalidPath", function (){ - htmx.off("htmx:invalidPath", listener); - done(); - }) - this.server.restore(); // use real xhrs - // will 404, but should respond - var btn = make('') - btn.click(); - }) - - it("can disable script tag support with htmx.config.allowScriptTags", function(){ - var globalWasCalled = false; - window.callGlobal = function() { - globalWasCalled = true; - } - try { - htmx.config.allowScriptTags = false; - this.server.respondWith("GET", "/test", "
    "); - var div = make("
    "); - div.click(); - this.server.respond(); - globalWasCalled.should.equal(false); - } finally { - htmx.config.allowScriptTags = true; - delete window.callGlobal; - } - }) -}); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/tokenizer.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/tokenizer.js deleted file mode 100644 index 3071ad9b169..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/tokenizer.js +++ /dev/null @@ -1,48 +0,0 @@ -describe("Core htmx tokenizer tests", function(){ - beforeEach(function() { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function() { - this.server.restore(); - clearWorkArea(); - }); - - function tokenize(str) { - return htmx._("tokenizeString")(str); - } - - function tokenizeTest(str, result) { - return tokenize(str).should.deep.equal(result); - } - - it('tokenizes properly', function() - { - tokenizeTest("", []); - tokenizeTest(" ", [" ", " "]); - tokenizeTest("(", ["("]); - tokenizeTest("()", ["(", ")"]); - tokenizeTest("(,)", ["(", ",", ")"]); - tokenizeTest(" ( ) ", [" ", "(", " ", ")", " "]); - tokenizeTest(" && ) ", [" ", "&", "&", " ", ")", " "]); - tokenizeTest(" && ) 'asdf'", [" ", "&", "&", " ", ")", " ", "'asdf'"]); - tokenizeTest(" && ) ',asdf'", [" ", "&", "&", " ", ")", " ", "',asdf'"]); - tokenizeTest('",asdf"', ['",asdf"']); - tokenizeTest('&& ) ",asdf"', ["&", "&", " ", ")", " ", '",asdf"']); - }); - - it('generates conditionals property', function() - { - var tokens = tokenize("[code==4||(code==5&&foo==true)]"); - var conditional = htmx._("maybeGenerateConditional")(null, tokens); - var func = eval(conditional); - func({code: 5, foo: true}).should.equal(true); - func({code: 5, foo: false}).should.equal(false); - func({code: 4, foo: false}).should.equal(true); - func({code: 3, foo: true}).should.equal(false); - }); - - - - -}) diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/validation.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/validation.js deleted file mode 100644 index 075e46391b1..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/validation.js +++ /dev/null @@ -1,204 +0,0 @@ -describe("Core htmx client side validation tests", function(){ - beforeEach(function() { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function() { - this.server.restore(); - clearWorkArea(); - }); - - it('HTML5 required validation error prevents request', function() - { - this.server.respondWith("POST", "/test", "Clicked!"); - - var form = make('
    ' + - 'No Request' + - '' + - '
    '); - form.textContent.should.equal("No Request"); - form.click(); - this.server.respond(); - form.textContent.should.equal("No Request"); - byId("i1").value = "foo"; - form.click(); - this.server.respond(); - form.textContent.should.equal("Clicked!"); - }); - - it('Novalidate skips form validation', function() - { - this.server.respondWith("POST", "/test", "Clicked!"); - - var form = make('
    ' + - 'No Request' + - '' + - '
    '); - form.textContent.should.equal("No Request"); - form.click(); - this.server.respond(); - form.textContent.should.equal("Clicked!"); - }); - - it('Validation skipped for indirect form submission', function() - { - this.server.respondWith("POST", "/test", "Clicked!"); - - var form = make('
    ' + - 'No Request' + - '' + - '' + - '
    '); - form.textContent.should.equal("No Request"); - byId("button").click(); - this.server.respond(); - form.textContent.should.equal("Clicked!"); - }); - - it('Formnovalidate skips form validation', function() - { - this.server.respondWith("POST", "/test", "Clicked!"); - - var form = make('
    ' + - 'No Request' + - '' + - '' + - '
    '); - form.textContent.should.equal("No Request"); - byId("button").click(); - this.server.respond(); - form.textContent.should.equal("Clicked!"); - }); - - it('HTML5 pattern validation error prevents request', function() - { - this.server.respondWith("POST", "/test", "Clicked!"); - - var form = make('
    ' + - 'No Request' + - '' + - '
    '); - byId("i1").value = "xyz"; - form.textContent.should.equal("No Request"); - form.click(); - this.server.respond(); - form.textContent.should.equal("No Request"); - byId("i1").value = "abc"; - form.click(); - this.server.respond(); - form.textContent.should.equal("Clicked!"); - }); - - it('Custom validation error prevents request', function() - { - this.server.respondWith("POST", "/test", "Clicked!"); - - var form = make('
    ' + - 'No Request' + - '' + - '
    '); - byId("i1").setCustomValidity("Nope"); - form.textContent.should.equal("No Request"); - form.click(); - this.server.respond(); - form.textContent.should.equal("No Request"); - byId("i1").setCustomValidity(""); - form.click(); - this.server.respond(); - form.textContent.should.equal("Clicked!"); - }); - - it('hyperscript validation error prevents request', function() - { - if (IsIE11()) { - this._runnable.title += " - Skipped as hyperscript isn't IE11 compatible" - this.skip() - return - } - - this.server.respondWith("POST", "/test", "Clicked!"); - - var form = make('
    ' + - 'No Request' + - '' + - '
    '); - htmx.trigger(form, "htmx:load"); - byId("i1").value = "boo"; - form.textContent.should.equal("No Request"); - form.click(); - this.server.respond(); - form.textContent.should.equal("No Request"); - byId("i1").value = "foo"; - form.click(); - this.server.respond(); - form.textContent.should.equal("Clicked!"); - }); - - it('calls htmx:validation:failed on failure', function() - { - var form = make('
    ' + - 'No Request' + - '' + - '
    '); - var calledEvent = false; - var handler = htmx.on(form, "htmx:validation:failed", function(){ - calledEvent = true; - }); - try { - form.click(); - this.server.respond(); - } finally { - htmx.off(form, handler); - } - calledEvent.should.equal(true); - }); - - it('calls htmx:validation:halted on failure', function() - { - var form = make('
    ' + - 'No Request' + - '' + - '
    '); - var errors = null; - var handler = htmx.on(form, "htmx:validation:halted", function(evt){ - errors = evt.detail.errors; - }); - try { - form.click(); - this.server.respond(); - } finally { - htmx.off(form, handler); - } - errors.length.should.equal(1); - byId("i1").should.equal(errors[0].elt); - errors[0].validity.valueMissing.should.equal(true); - }); - - - it('hx-validate can prevent a single input from submitting', function() - { - this.server.respondWith("POST", "/test", "Clicked!"); - var div = make("
    No Request
    ") - var form = make('
    '); - var input = byId("i1"); - - div.textContent.should.equal("No Request"); - - input.value = "abc"; - input.click(); - this.server.respond(); - div.textContent.should.equal("No Request"); - - input.value = "1bc"; - input.click(); - this.server.respond(); - div.textContent.should.equal("No Request"); - - input.value = "123"; - input.click(); - this.server.respond(); - div.textContent.should.equal("Clicked!"); - }); - -}) diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/verbs.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/verbs.js deleted file mode 100644 index 1d0711c2f45..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/core/verbs.js +++ /dev/null @@ -1,44 +0,0 @@ -describe("Core htmx AJAX Verbs", function() { - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it('handles basic posts properly', function () { - this.server.respondWith("POST", "/test", "post"); - var div = make('
    click me
    '); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("post"); - }) - - it('handles basic put properly', function () { - this.server.respondWith("PUT", "/test", "put"); - var div = make('
    click me
    '); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("put"); - }) - - it('handles basic patch properly', function () { - this.server.respondWith("PATCH", "/test", "patch"); - var div = make('
    click me
    '); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("patch"); - }) - - it('handles basic delete properly', function () { - this.server.respondWith("DELETE", "/test", "delete"); - var div = make('
    click me
    '); - div.click(); - this.server.respond(); - div.innerHTML.should.equal("delete"); - }) - -}); - diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/ajax-header.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/ajax-header.js deleted file mode 100644 index 0888ef3b54f..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/ajax-header.js +++ /dev/null @@ -1,21 +0,0 @@ -describe("ajax-header extension", function() { - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it('Sends the X-Requested-With header', function () { - this.server.respondWith("GET", "/test", function (xhr) { - xhr.respond(200, {}, xhr.requestHeaders['X-Requested-With']) - }); - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("XMLHttpRequest"); - }); - -}); \ No newline at end of file diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/bad-extension.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/bad-extension.js deleted file mode 100644 index 3f38748dd3d..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/bad-extension.js +++ /dev/null @@ -1,27 +0,0 @@ -describe("bad extension", function() { - htmx.defineExtension("bad-extension", { - onEvent : function(name, evt) {throw "onEvent"}, - transformResponse : function(text, xhr, elt) {throw "transformRequest"}, - isInlineSwap : function(swapStyle) {throw "isInlineSwap"}, - handleSwap : function(swapStyle, target, fragment, settleInfo) {throw "handleSwap"}, - encodeParameters : function(xhr, parameters, elt) {throw "encodeParameters"} - } - ) - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it('does not blow up rendering', function () { - this.server.respondWith("GET", "/test", "clicked!"); - var div = make('
    Click Me!
    ') - div.click(); - this.server.respond(); - div.innerHTML.should.equal("clicked!"); - }); - -}); \ No newline at end of file diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/class-tools.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/class-tools.js deleted file mode 100644 index 0c5004b5612..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/class-tools.js +++ /dev/null @@ -1,55 +0,0 @@ -describe("class-tools extension", function(){ - beforeEach(function() { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function() { - this.server.restore(); - clearWorkArea(); - }); - - it('adds classes properly', function(done) - { - var div = make('
    Click Me!
    ') - should.equal(div.classList.length, 0); - setTimeout(function(){ - should.equal(div.classList.contains("c1"), true); - done(); - }, 100); - }); - - it('removes classes properly', function(done) - { - var div = make('
    Click Me!
    ') - should.equal(div.classList.contains("foo"), true); - should.equal(div.classList.contains("bar"), true); - setTimeout(function(){ - should.equal(div.classList.contains("foo"), true); - should.equal(div.classList.contains("bar"), false); - done(); - }, 100); - }); - - it('adds classes properly w/ data-* prefix', function(done) - { - var div = make('
    Click Me!
    ') - should.equal(div.classList.length, 0); - setTimeout(function(){ - should.equal(div.classList.contains("c1"), true); - done(); - }, 100); - }); - - it('extension can be on parent', function(done) - { - var div = make('
    Click Me!
    ') - should.equal(div.classList.length, 0); - setTimeout(function(){ - should.equal(div.classList.contains("c1"), false); - should.equal(byId("d1").classList.contains("c1"), true); - done(); - }, 100); - }); - - -}) diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/client-side-templates.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/client-side-templates.js deleted file mode 100644 index c6fdd3261b6..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/client-side-templates.js +++ /dev/null @@ -1,59 +0,0 @@ -describe("client-side-templates extension", function() { - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it('works on basic mustache template', function () { - this.server.respondWith("GET", "/test", '{"foo":"bar"}'); - var btn = make('') - make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("*bar*"); - }); - - it('works on mustache array template', function () { - this.server.respondWith("GET", "/test", '{"foo":"bar"}'); - var btn = make('') - make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("*bar*"); - }); - - it('works on basic handlebars template', function () { - this.server.respondWith("GET", "/test", '{"foo":"bar"}'); - var btn = make('') - make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("*bar*"); - }); - - it('works on handlebars array template', function () { - this.server.respondWith("GET", "/test", '[{"foo":"bar"}]'); - var btn = make('') - make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("*bar*"); - }); - - it('works on basic xslt template', function () { - this.server.respondWith("GET", "/test", 'bar'); - var btn = make('') - make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("*bar*"); - }); -}); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/debug.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/debug.js deleted file mode 100644 index 4eeca295e63..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/debug.js +++ /dev/null @@ -1,19 +0,0 @@ -describe("debug extension", function() { - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it('works on basic request', function () { - this.server.respondWith("GET", "/test", "Clicked!"); - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - }); - -}); \ No newline at end of file diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/disable-element.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/disable-element.js deleted file mode 100644 index 58e5a732477..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/disable-element.js +++ /dev/null @@ -1,90 +0,0 @@ -describe("disable-element extension", function() { - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it('disables the triggering element during htmx request', function () { - // GIVEN: - // - A button triggering an htmx request with disable-element extension - // - The button is enabled - this.server.respondWith("GET", "/test", function (xhr) { - xhr.respond(200, {}) - }); - var btn = make('') - btn.disabled.should.equal(false); - - // WHEN clicking - btn.click(); - - // THEN it's disabled - btn.disabled.should.equal(true); - - // WHEN server response has arrived - this.server.respond(); - - // THEN it's re-enabled - btn.disabled.should.equal(false); - }); - - it('disables the designated element during htmx request', function () { - // GIVEN: - // - A button triggering an htmx request with disable-element extension - // - Another button that needs to be disabled during the htmx request - // - Both buttons are enabled - this.server.respondWith("GET", "/test", function (xhr) { - xhr.respond(200, {}) - }); - var btn = make('') - var btn2 = make('') - btn.disabled.should.equal(false); - btn2.disabled.should.equal(false); - - // WHEN clicking - btn.click(); - - // THEN it's not disabled, but the other one is - btn.disabled.should.equal(false); - btn2.disabled.should.equal(true); - - // WHEN server response has arrived - this.server.respond(); - - // THEN both buttons are back enabled - btn.disabled.should.equal(false); - btn2.disabled.should.equal(false); - }); - - it('disables multiple elements during htmx request', function () { - this.server.respondWith("GET", "/test", function (xhr) { - xhr.respond(200, {}) - }); - var btn = make('') - var btn2 = make('') - var btn3 = make('') - btn.disabled.should.equal(false); - btn2.disabled.should.equal(false); - btn3.disabled.should.equal(false); - - // WHEN clicking - btn.click(); - - // THEN the first two are disabled, but the last one isn't - btn.disabled.should.equal(true); - btn2.disabled.should.equal(true); - btn3.disabled.should.equal(false); - - // WHEN server response has arrived - this.server.respond(); - - // THEN all buttons are back enabled - btn.disabled.should.equal(false); - btn2.disabled.should.equal(false); - btn3.disabled.should.equal(false); - }); - -}); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/event-header.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/event-header.js deleted file mode 100644 index a5a66cf580a..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/event-header.js +++ /dev/null @@ -1,23 +0,0 @@ -describe("event-header extension", function() { - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it('Sends the Triggering-Event header', function () { - this.server.respondWith("GET", "/test", function (xhr) { - xhr.respond(200, {}, xhr.requestHeaders['Triggering-Event']) - }); - var btn = make('') - btn.click(); - this.server.respond(); - var json = JSON.parse(btn.innerText); - json.type.should.equal("click"); - json.target.should.equal("button"); - }); - -}); \ No newline at end of file diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/extension-swap.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/extension-swap.js deleted file mode 100644 index 0186b525048..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/extension-swap.js +++ /dev/null @@ -1,60 +0,0 @@ -describe("default extensions behavior", function() { - - var loadCalls, afterSwapCalls, afterSettleCalls; - - beforeEach(function () { - loadCalls = []; - this.server = makeServer(); - clearWorkArea(); - - htmx.defineExtension("ext-testswap", { - onEvent : function(name, evt) { - if (name === "htmx:load") { - loadCalls.push(evt.detail.elt); - } - }, - handleSwap: function (swapStyle, target, fragment, settleInfo) { - // simple outerHTML replacement for tests - var parentEl = target.parentElement; - parentEl.removeChild(target); - return [parentEl.appendChild(fragment)]; // return the newly added element - } - - }); - - }); - - afterEach(function () { - this.server.restore(); - clearWorkArea(); - htmx.removeExtension("ext-testswap"); - }); - - it('handleSwap: afterSwap and afterSettle triggered if extension defined on parent', function () { - this.server.respondWith("GET", "/test", ''); - var div = make('
    '); - var btn = div.firstChild; - btn.click() - this.server.respond(); - loadCalls.length.should.equal(1); - loadCalls[0].textContent.should.equal('Clicked!'); // the new button is loaded - }); - - it('handleSwap: new content is handled by htmx', function() { - this.server.respondWith("GET", "/test", ''); - this.server.respondWith("GET", "/test-inner", 'Loaded!'); - make('
    ').querySelector('button').click(); - - this.server.respond(); // call /test via button trigger=click - var btn = byId('test-ext-testswap'); - btn.textContent.should.equal('Clicked!'); - loadCalls.length.should.equal(1); - loadCalls[0].textContent.should.equal('Clicked!'); // the new button is loaded - - this.server.respond(); // call /test-inner via span trigger=load - btn.textContent.should.equal("Clicked!Loaded!"); - loadCalls.length.should.equal(2); - loadCalls[1].textContent.should.equal('Loaded!'); // the new span is loaded - }); - -}); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/hyperscript.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/hyperscript.js deleted file mode 100644 index 67889d0506c..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/hyperscript.js +++ /dev/null @@ -1,69 +0,0 @@ -describe("hyperscript integration", function() { - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - - if (IsIE11()) { - this.title += " - Skipped as hyperscript isn't IE11 compatible" - this.skip() - } - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it('can trigger with a custom event', function () { - this.server.respondWith("GET", "/test", "Custom Event Sent!"); - var btn = make('') - htmx.trigger(btn, "htmx:load"); // have to manually trigger the load event for non-AJAX dynamic content - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Custom Event Sent!"); - }); - - it('can handle htmx driven events', function () { - this.server.respondWith("GET", "/test", "Clicked!"); - var btn = make('') - htmx.trigger(btn, "htmx:load"); - btn.classList.contains("afterSettle").should.equal(false); - btn.click(); - this.server.respond(); - btn.classList.contains("afterSettle").should.equal(true); - }); - - it('can handle htmx error events', function () { - this.server.respondWith("GET", "/test", [404, {}, "Bad request"]); - var div = make('
    ') - var btn = make('') - htmx.trigger(btn, "htmx:load"); - btn.click(); - this.server.respond(); - div.innerHTML.startsWith("Response Status Error Code 404 from"); - }); - - it('hyperscript in non-htmx annotated nodes is evaluated', function () { - this.server.respondWith("GET", "/test", "
    "); - var btn = make('') - btn.click(); - this.server.respond(); - var newDiv = byId("d1"); - newDiv.click(); - newDiv.innerText.should.equal("Clicked..."); - }); - - it('hyperscript removal example works', function (done) { - this.server.respondWith("GET", "/test", "
    To Remove
    "); - var btn = make('') - btn.click(); - this.server.respond(); - var newDiv = byId("d1"); - newDiv.innerText.should.equal("To Remove") - setTimeout(function(){ - newDiv = byId("d1"); - should.equal(newDiv, null); - done(); - }, 100); - }); - -}); \ No newline at end of file diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/include-vals.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/include-vals.js deleted file mode 100644 index fc05a067b3b..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/include-vals.js +++ /dev/null @@ -1,23 +0,0 @@ -describe("include-vals extension", function() { - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it('Includes values properly', function () { - var params = {}; - this.server.respondWith("POST", "/test", function (xhr) { - params = getParameters(xhr); - xhr.respond(200, {}, "clicked"); - }); - var btn = make('') - btn.click(); - this.server.respond(); - params['foo'].should.equal("bar"); - }); - -}); \ No newline at end of file diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/json-enc.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/json-enc.js deleted file mode 100644 index 88ba0b65d1b..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/json-enc.js +++ /dev/null @@ -1,143 +0,0 @@ -describe("json-enc extension", function() { - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it('handles basic get properly', function () { - var jsonResponseBody = JSON.stringify({}); - this.server.respondWith("GET", "/test", jsonResponseBody); - var div = make('
    click me
    '); - div.click(); - this.server.respond(); - this.server.lastRequest.response.should.equal("{}"); - }) - - it('handles basic post properly', function () { - var jsonResponseBody = JSON.stringify({}); - this.server.respondWith("POST", "/test", jsonResponseBody); - var div = make("
    click me
    "); - div.click(); - this.server.respond(); - this.server.lastRequest.response.should.equal("{}"); - }) - - it('handles basic put properly', function () { - var jsonResponseBody = JSON.stringify({}); - this.server.respondWith("PUT", "/test", jsonResponseBody); - var div = make('
    click me
    '); - div.click(); - this.server.respond(); - this.server.lastRequest.response.should.equal("{}"); - }) - - it('handles basic patch properly', function () { - var jsonResponseBody = JSON.stringify({}); - this.server.respondWith("PATCH", "/test", jsonResponseBody); - var div = make('
    click me
    '); - div.click(); - this.server.respond(); - this.server.lastRequest.response.should.equal("{}"); - }) - - it('handles basic delete properly', function () { - var jsonResponseBody = JSON.stringify({}); - this.server.respondWith("DELETE", "/test", jsonResponseBody); - var div = make('
    click me
    '); - div.click(); - this.server.respond(); - this.server.lastRequest.response.should.equal("{}"); - }) - - it('handles post with form parameters', function () { - - this.server.respondWith("POST", "/test", function (xhr) { - var values = JSON.parse(xhr.requestBody); - values.should.have.keys("username","password"); - values["username"].should.be.equal("joe"); - values["password"].should.be.equal("123456"); - var ans = { "passwordok": values["password"] == "123456"}; - xhr.respond(200, {}, JSON.stringify(ans)); - }); - - var html = make('
    ' + - ' ' + - ' ' + - ' '); - - byId("btnSubmit").click(); - this.server.respond(); - this.server.lastRequest.response.should.equal('{"passwordok":true}'); - }) - - it('handles put with form parameters', function () { - this.server.respondWith("PUT", "/test", function (xhr) { - var values = JSON.parse(xhr.requestBody); - values.should.have.keys("username","password"); - values["username"].should.be.equal("joe"); - values["password"].should.be.equal("123456"); - var ans = { "passwordok": values["password"] == "123456"}; - xhr.respond(200, {}, JSON.stringify(ans)); - }); - - var html = make(' ' + - ' ' + - ' ' + - ' '); - - byId("btnSubmit").click(); - this.server.respond(); - this.server.lastRequest.response.should.equal('{"passwordok":true}'); - }) - - - it('handles patch with form parameters', function () { - - this.server.respondWith("PATCH", "/test", function (xhr) { - var values = JSON.parse(xhr.requestBody); - values.should.have.keys("username","password"); - values["username"].should.be.equal("joe"); - values["password"].should.be.equal("123456"); - var ans = { "passwordok": values["password"] == "123456"}; - xhr.respond(200, {}, JSON.stringify(ans)); - }); - - var html = make(' ' + - ' ' + - ' ' + - ' '); - - byId("btnSubmit").click(); - this.server.respond(); - this.server.lastRequest.response.should.equal('{"passwordok":true}'); - }) - - it('handles delete with form parameters', function () { - - this.server.respondWith("DELETE", "/test", function (xhr) { - var values = JSON.parse(xhr.requestBody); - values.should.have.keys("username","password"); - values["username"].should.be.equal("joe"); - values["password"].should.be.equal("123456"); - var ans = { "passwordok": values["password"] == "123456"}; - xhr.respond(200, {}, JSON.stringify(ans)); - }); - - var html = make(' ' + - ' ' + - ' ' + - ' '); - - byId("btnSubmit").click(); - this.server.respond(); - this.server.lastRequest.response.should.equal('{"passwordok":true}'); - }) - - - -}); - diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/loading-states.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/loading-states.js deleted file mode 100644 index d73634d46bc..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/loading-states.js +++ /dev/null @@ -1,167 +0,0 @@ -describe("loading states extension", function () { - beforeEach(function () { - this.server = makeServer(); - this.clock = sinon.useFakeTimers(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - this.clock.restore(); - clearWorkArea(); - }); - - it('works on basic setup', function () { - this.server.respondWith("GET", "/test", "Clicked!"); - var btn = make(''); - var element = make('
    '); - btn.click(); - element.style.display.should.be.equal("inline-block"); - this.server.respond(); - element.style.display.should.be.equal("none"); - btn.innerHTML.should.equal("Clicked!"); - }); - - it('works with custom display', function () { - this.server.respondWith("GET", "/test", "Clicked!"); - var btn = make(''); - var element = make('
    '); - btn.click(); - element.style.display.should.be.equal("flex"); - this.server.respond(); - element.style.display.should.be.equal("none"); - btn.innerHTML.should.equal("Clicked!"); - }); - - it('works with classes', function () { - this.server.respondWith("GET", "/test", "Clicked!"); - var btn = make(''); - var element = make('
    '); - btn.click(); - element.should.have.class("test"); - this.server.respond(); - element.should.not.have.class("test"); - btn.innerHTML.should.equal("Clicked!"); - }); - - it('works with classes removal', function () { - this.server.respondWith("GET", "/test", "Clicked!"); - var btn = make(''); - var element = make('
    '); - btn.click(); - element.should.not.have.class("test"); - this.server.respond(); - element.should.have.class("test"); - btn.innerHTML.should.equal("Clicked!"); - }); - - it('works with disabling', function () { - this.server.respondWith("GET", "/test", "Clicked!"); - var btn = make(''); - var element = make(''); - var element = make(''); - var element = make(''); - var element = make('
    '); - btn.click(); - element.should.have.class("test"); - this.clock.tick(1000); - element.should.not.have.class("test"); - this.server.respond(); - element.should.have.class("test"); - btn.innerHTML.should.equal("Clicked!"); - }); - - it('works with custom targets', function () { - this.server.respondWith("GET", "/test", "Clicked!"); - var btn = make(''); - var element = make('
    '); - btn.click(); - element.should.have.class("test"); - this.server.respond(); - element.should.not.have.class("test"); - btn.innerHTML.should.equal("Clicked!"); - }); - - it('works with path filters', function () { - this.server.respondWith("GET", "/test", "Clicked!"); - var btn = make(''); - var matchingRequestElement = make('
    '); - var nonMatchingPathElement = make('
    '); - btn.click(); - matchingRequestElement.should.have.class("test"); - nonMatchingPathElement.should.not.have.class("test"); - this.server.respond(); - matchingRequestElement.should.not.have.class("test"); - nonMatchingPathElement.should.not.have.class("test"); - btn.innerHTML.should.equal("Clicked!"); - }); - - it('works with scopes', function () { - this.server.respondWith("GET", "/test", "Clicked!"); - var btn = make('
    '); - var element = make('
    '); - btn.getElementsByTagName("button")[0].click(); - element.should.not.have.class("test"); - this.server.respond(); - element.should.not.have.class("test"); - btn.getElementsByTagName("button")[0].innerHTML.should.equal("Clicked!"); - }); - - it('history restore should not have loading states in content', function () { - // this test is based on test from test/attributes/hx-push-url.js:65 - this.server.respondWith("GET", "/test1", ''); - this.server.respondWith("GET", "/test2", ''); - - make('
    '); - - byId("d1").click(); - byId("d1").disabled.should.be.true; - this.server.respond(); - byId("d2").disabled.should.be.false; - var workArea = getWorkArea(); - workArea.textContent.should.equal("test1"); - - byId("d2").click(); - byId("d2").disabled.should.be.true; - this.server.respond(); - workArea.textContent.should.equal("test2") - - htmx._('restoreHistory')("/test1") - - var el = byId("d2"); - el.disabled.should.be.false; - }) -}); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/method-override.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/method-override.js deleted file mode 100644 index b0a21ea1df9..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/method-override.js +++ /dev/null @@ -1,53 +0,0 @@ -describe("method-override extension", function(){ - beforeEach(function() { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function() { - this.server.restore(); - clearWorkArea(); - }); - - it('issues a DELETE request with proper headers', function() - { - this.server.respondWith("DELETE", "/test", function(xhr){ - xhr.requestHeaders['X-HTTP-Method-Override'].should.equal('DELETE'); - xhr.method.should.equal("POST") - xhr.respond(200, {}, "Deleted!"); - }); - - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Deleted!"); - }); - - it('issues a PATCH request with proper headers', function() - { - this.server.respondWith("PATCH", "/test", function(xhr){ - xhr.requestHeaders['X-HTTP-Method-Override'].should.equal('PATCH'); - xhr.method.should.equal("POST") - xhr.respond(200, {}, "Patched!"); - }); - - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Patched!"); - }); - - it('issues a PUT request with proper headers', function() - { - this.server.respondWith("PUT", "/test", function(xhr){ - xhr.requestHeaders['X-HTTP-Method-Override'].should.equal('PUT'); - xhr.method.should.equal("POST") - xhr.respond(200, {}, "Putted!"); - }); - - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Putted!"); - }); - -}) diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/morphdom-swap.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/morphdom-swap.js deleted file mode 100644 index 439fa54cf2c..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/morphdom-swap.js +++ /dev/null @@ -1,40 +0,0 @@ -describe("morphdom-swap extension", function() { - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it('works on basic request', function () { - this.server.respondWith("GET", "/test", "!"); - var btn = make('') - btn.click(); - should.equal(btn.getAttribute("hx-get"), "/test"); - this.server.respond(); - should.equal(btn.getAttribute("hx-get"), null); - btn.innerHTML.should.equal("Clicked!"); - }); - - it('works with htmx elements in new content', function () { - this.server.respondWith("GET", "/test", ''); - this.server.respondWith("GET", "/test-inner", 'Loaded!'); - var btn = make('
    ').querySelector('button'); - btn.click(); - this.server.respond(); // call /test via button trigger=click - this.server.respond(); // call /test-inner via span trigger=load - btn.innerHTML.should.equal("Clicked!Loaded!"); - }); - - it('works with hx-select', function () { - this.server.respondWith("GET", "/test", "!"); - var btn = make('') - btn.click(); - should.equal(btn.getAttribute("hx-get"), "/test"); - this.server.respond(); - should.equal(btn.getAttribute("hx-get"), null); - btn.innerHTML.should.equal("Clicked!"); - }); -}); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/multi-swap.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/multi-swap.js deleted file mode 100644 index 70b09821a2c..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/multi-swap.js +++ /dev/null @@ -1,52 +0,0 @@ -describe("multi-swap extension", function() { - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it('swap only one element with default innerHTML', function () { - this.server.respondWith("GET", "/test", '
    New A
    '); - var content = make('
    Foo
    Old A
    '); - var btn = make(''); - btn.click(); - this.server.respond(); - should.equal(content.innerHTML, 'Foo
    New A
    '); - }); - - it('swap multiple elements with outerHTML, beforeend, afterend, beforebegin and delete methods', function () { - this.server.respondWith("GET", "/test", - '
    ' + - '
    New A
    foo ' + - '
    New B
    bar ' + - '
    New C
    dummy ' + - '
    New D
    lorem ' + - '
    TO DELETE
    ' + - '
    ' - ); - var content = make( - '
    Foo ' + - '
    Old A
    A ' + - '
    Old B
    B ' + - '
    Old C
    C ' + - '
    Old D
    D ' + - '
    Old E
    E ' + - '
    ' - ); - var btn = make(''); - btn.click(); - this.server.respond(); - should.equal(content.outerHTML, - '
    Foo ' + - '
    New A
    A ' + - '
    Old BNew B
    B ' + - '
    Old C
    New C C ' + - ' New D
    Old D
    D ' + - ' E ' + - '
    ' - ); - }); -}); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/path-deps.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/path-deps.js deleted file mode 100644 index 9b1569acebe..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/path-deps.js +++ /dev/null @@ -1,173 +0,0 @@ -describe("path-deps extension", function() { - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it('path-deps basic case works', function () { - this.server.respondWith("POST", "/test", "Clicked!"); - this.server.respondWith("GET", "/test2", "Deps fired!"); - var btn = make('') - var div = make('
    FOO
    ') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - div.innerHTML.should.equal("FOO"); - this.server.respond(); - div.innerHTML.should.equal("Deps fired!"); - }); - - it('path-deps works with trailing slash', function () { - this.server.respondWith("POST", "/test", "Clicked!"); - this.server.respondWith("GET", "/test2", "Deps fired!"); - var btn = make('') - var div = make('
    FOO
    ') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - div.innerHTML.should.equal("FOO"); - this.server.respond(); - div.innerHTML.should.equal("Deps fired!"); - }); - - it('path-deps GET does not trigger', function () { - this.server.respondWith("GET", "/test", "Clicked!"); - this.server.respondWith("GET", "/test2", "Deps fired!"); - var btn = make('') - var div = make('
    FOO
    ') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - div.innerHTML.should.equal("FOO"); - this.server.respond(); - div.innerHTML.should.equal("FOO"); - }); - - it('path-deps dont trigger on path mismatch', function () { - this.server.respondWith("POST", "/test", "Clicked!"); - this.server.respondWith("GET", "/test2", "Deps fired!"); - var btn = make('') - var div = make('
    FOO
    ') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - div.innerHTML.should.equal("FOO"); - this.server.respond(); - div.innerHTML.should.equal("FOO"); - }); - - it('path-deps dont trigger on path longer than request', function () { - this.server.respondWith("POST", "/test", "Clicked!"); - this.server.respondWith("GET", "/test2", "Deps fired!"); - var btn = make('') - var div = make('
    FOO
    ') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - div.innerHTML.should.equal("FOO"); - this.server.respond(); - div.innerHTML.should.equal("FOO"); - }); - - it('path-deps trigger on path shorter than request', function () { - this.server.respondWith("POST", "/test/child", "Clicked!"); - this.server.respondWith("GET", "/test2", "Deps fired!"); - var btn = make('') - var div = make('
    FOO
    ') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - div.innerHTML.should.equal("FOO"); - this.server.respond(); - div.innerHTML.should.equal("Deps fired!"); - }); - - it('path-deps trigger on *-at-start path', function () { - this.server.respondWith("POST", "/test/child/test", "Clicked!"); - this.server.respondWith("GET", "/test2", "Deps fired!"); - var btn = make('') - var div = make('
    FOO
    ') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - div.innerHTML.should.equal("FOO"); - this.server.respond(); - div.innerHTML.should.equal("Deps fired!"); - }); - - it('path-deps trigger on *-in-middle path', function () { - this.server.respondWith("POST", "/test/child/test", "Clicked!"); - this.server.respondWith("GET", "/test2", "Deps fired!"); - var btn = make('') - var div = make('
    FOO
    ') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - div.innerHTML.should.equal("FOO"); - this.server.respond(); - div.innerHTML.should.equal("Deps fired!"); - }); - - it('path-deps trigger on *-at-end path', function () { - this.server.respondWith("POST", "/test/child/test", "Clicked!"); - this.server.respondWith("GET", "/test2", "Deps fired!"); - var btn = make('') - var div = make('
    FOO
    ') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - div.innerHTML.should.equal("FOO"); - this.server.respond(); - div.innerHTML.should.equal("Deps fired!"); - }); - - it('path-deps trigger all *s path', function () { - this.server.respondWith("POST", "/test/child/test", "Clicked!"); - this.server.respondWith("GET", "/test2", "Deps fired!"); - var btn = make('') - var div = make('
    FOO
    ') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Clicked!"); - div.innerHTML.should.equal("FOO"); - this.server.respond(); - div.innerHTML.should.equal("Deps fired!"); - }); - - it('path-deps api basic refresh case works', function () { - this.server.respondWith("GET", "/test", "Path deps fired!"); - var div = make('
    FOO
    ') - PathDeps.refresh("/test"); - this.server.respond(); - div.innerHTML.should.equal("Path deps fired!"); - }); - - it('path-deps api parent path case works', function () { - this.server.respondWith("GET", "/test1", "Path deps 1 fired!"); - this.server.respondWith("GET", "/test2", "Path deps 2 fired!"); - var div = make('
    FOO
    ') - var div2 = make('
    BAR
    ') - PathDeps.refresh("/test/child"); - this.server.respond(); - div.innerHTML.should.equal("Path deps 1 fired!"); - this.server.respond(); - div2.innerHTML.should.equal("Path deps 2 fired!"); - }); - - it('path-deps replacing containing element fires event', function () { - this.server.respondWith("POST", "/test", "Clicked!"); - this.server.respondWith("GET", "/test2", "Deps fired!"); - var div1 = make('
    ') - var div2 = make('
    FOO
    ') - byId("buttonSubmit").click(); - this.server.respond(); - div1.innerHTML.should.equal('Clicked!'); - div2.innerHTML.should.equal("FOO"); - this.server.respond(); - div2.innerHTML.should.equal("Deps fired!"); - }); -}); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/path-params.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/path-params.js deleted file mode 100644 index 3f0ac3a3c64..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/path-params.js +++ /dev/null @@ -1,51 +0,0 @@ -describe("path-params extension", function() { - beforeEach(function () { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - }); - - it('uses parameter to populate path variable', function () { - var request; - htmx.on("htmx:beforeRequest", function (evt) { - request = evt; - }); - var div = make("
    ") - div.click(); - should.equal(request.detail.requestConfig.path, '/items/42'); - }); - - it('parameter is removed when used', function () { - var request; - htmx.on("htmx:beforeRequest", function (evt) { - request = evt; - }); - var div = make("
    ") - div.click(); - should.equal(request.detail.requestConfig.parameters.other, 43); - should.equal(request.detail.requestConfig.parameters.itemId, undefined); - }); - - it('parameter value is encoded', function () { - var request; - htmx.on("htmx:beforeRequest", function (evt) { - request = evt; - }); - var div = make("
    ") - div.click(); - should.equal(request.detail.requestConfig.path, '/items/a%2Fb'); - }); - - it('missing variables are ignored', function () { - var request; - htmx.on("htmx:beforeRequest", function (evt) { - request = evt; - }); - var div = make("
    ") - div.click(); - should.equal(request.detail.requestConfig.path, '/items/42/{subitem}'); - }); -}); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/remove-me.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/remove-me.js deleted file mode 100644 index cdfd51f8337..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/remove-me.js +++ /dev/null @@ -1,53 +0,0 @@ -describe("remove-me extension", function(){ - beforeEach(function() { - this.server = makeServer(); - clearWorkArea(); - }); - afterEach(function() { - this.server.restore(); - clearWorkArea(); - }); - - it('removes elements properly', function(done) - { - var div = make('
    Click Me!
    ') - byId("d1").should.equal(div) - setTimeout(function(){ - should.equal(byId("d1"), null); - done(); - }, 40); - }); - - - it('removes properly w/ data-* prefix', function(done) - { - var div = make('
    Click Me!
    ') - should.equal(div.classList.length, 0); - setTimeout(function(){ - should.equal(div.parentElement, null); - done(); - }, 100); - }); - - it('extension can be on parent', function(done) - { - var div = make('
    Click Me!
    ') - should.equal(div.classList.length, 0); - setTimeout(function(){ - should.equal(byId("d1"), null); - done(); - }, 100); - }); - - it('extension can be on a child', function(done) - { - var div = make('
    Click Me!
    ') - should.equal(div.classList.length, 0); - setTimeout(function(){ - should.equal(byId("d1"), null); - done(); - }, 100); - }); - - -}) diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/response-targets.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/response-targets.js deleted file mode 100644 index 2384c319b07..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/response-targets.js +++ /dev/null @@ -1,300 +0,0 @@ -describe("response-targets extension", function() { - beforeEach(function() { - this.server = sinon.fakeServer.create(); - clearWorkArea(); - }); - afterEach(function() { - this.server.restore(); - clearWorkArea(); - }); - - it('targets an adjacent element properly', function() - { - this.server.respondWith("GET", "/test", [404, {}, "Not found!"]); - var btn = make('') - var div1 = make('
    ') - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal("Not found!"); - }); - - it('targets an adjacent element properly with wildcard', function() - { - this.server.respondWith("GET", "/test", [404, {}, "Not found!"]); - var btn = make('') - var div1 = make('
    ') - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal("Not found!"); - }); - - it('targets a parent element properly', function() - { - this.server.respondWith("GET", "/test", [404, {}, "Not found!"]); - var div1 = make('
    ') - var btn = byId("b1") - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal("Not found!"); - }); - - it('targets a parent element properly with wildcard', function() - { - this.server.respondWith("GET", "/test", [404, {}, "Not found!"]); - var div1 = make('
    ') - var btn = byId("b1") - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal("Not found!"); - }); - - it('targets a `this` element properly', function() - { - this.server.respondWith("GET", "/test", [404, {}, "Not found!"]); - var div1 = make('
    ') - var btn = byId("b1") - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal("Not found!"); - }); - - it('targets a `closest` element properly', function() - { - this.server.respondWith("GET", "/test", [404, {}, "Not found!"]); - var div1 = make('

    ') - var btn = byId("b1") - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal("Not found!"); - }); - - it('targets a `closest` element properly w/ hyperscript syntax', function() - { - this.server.respondWith("GET", "/test", [404, {}, "Not found!"]); - var div1 = make('

    ') - var btn = byId("b1") - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal("Not found!"); - }); - - it('targets a `find` element properly', function() - { - this.server.respondWith("GET", "/test", [404, {}, "Not found!"]); - var div1 = make('
    Click Me!
    ') - div1.click(); - this.server.respond(); - var span1 = byId("s1") - var span2 = byId("s2") - span1.innerHTML.should.equal("Not found!"); - span2.innerHTML.should.equal(""); - }); - - it('targets a `find` element properly w/ hyperscript syntax', function() - { - this.server.respondWith("GET", "/test", [404, {}, "Not found!"]); - var div1 = make('
    Click Me!
    ') - div1.click(); - this.server.respond(); - var span1 = byId("s1") - var span2 = byId("s2") - span1.innerHTML.should.equal("Not found!"); - span2.innerHTML.should.equal(""); - }); - - it('targets an inner element properly', function() - { - this.server.respondWith("GET", "/test", [404, {}, "Not found!"]); - var btn = make('') - var div1 = byId("d1") - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal("Not found!"); - }); - - it('targets an inner element properly w/ hyperscript syntax', function() - { - this.server.respondWith("GET", "/test", [404, {}, "Not found!"]); - var btn = make('') - var div1 = byId("d1") - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal("Not found!"); - }); - - it('handles bad target gracefully', function() - { - this.server.respondWith("GET", "/test", [404, {}, "Not found!"]); - var btn = make('') - btn.click(); - this.server.respond(); - btn.innerHTML.should.equal("Click Me!"); - }); - - - it('targets an adjacent element properly w/ data-* prefix', function() - { - this.server.respondWith("GET", "/test", [404, {}, "Not found!"]); - var btn = make('') - var div1 = make('
    ') - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal("Not found!"); - }); - - it('targets a `next` element properly', function() - { - this.server.respondWith("GET", "/test", [404, {}, "Not found!"]); - make('
    ' + - '
    ' + - ' ' + - '
    ' + - '
    ' + - '
    ') - var btn = byId("b1") - var div1 = byId("d1") - var div2 = byId("d2") - var div3 = byId("d3") - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal("Not found!"); - div2.innerHTML.should.equal(""); - div3.innerHTML.should.equal(""); - }); - - it('targets a `next` element properly w/ hyperscript syntax', function() - { - this.server.respondWith("GET", "/test", [404, {}, "Not found!"]); - make('
    ' + - '
    ' + - ' ' + - '
    ' + - '
    ' + - '
    ') - var btn = byId("b1") - var div1 = byId("d1") - var div2 = byId("d2") - var div3 = byId("d3") - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal("Not found!"); - div2.innerHTML.should.equal(""); - div3.innerHTML.should.equal(""); - }); - - it('targets a `previous` element properly', function() - { - this.server.respondWith("GET", "/test", [404, {}, "Not found!"]); - make('
    ' + - '
    ' + - ' ' + - '
    ' + - '
    ' + - '
    ') - var btn = byId("b1") - var div1 = byId("d1") - var div2 = byId("d2") - var div3 = byId("d3") - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal(""); - div2.innerHTML.should.equal(""); - div3.innerHTML.should.equal("Not found!"); - }); - - it('targets a `previous` element properly w/ hyperscript syntax', function() - { - this.server.respondWith("GET", "/test", [404, {}, "Not found!"]); - make('
    ' + - '
    ' + - ' ' + - '
    ' + - '
    ' + - '
    ') - var btn = byId("b1") - var div1 = byId("d1") - var div2 = byId("d2") - var div3 = byId("d3") - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal(""); - div2.innerHTML.should.equal(""); - div3.innerHTML.should.equal("Not found!"); - }); - - it('targets the element specified in headers if configured to prefer it (default)', function () { - this.server.respondWith("GET", "/test", [404, { "HX-Retarget": "#d2" }, "Not found!"]); - var btn = make('') - var div1 = make('
    ') - var div2 = make('
    ') - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal(""); - div2.innerHTML.should.equal("Not found!"); - }); - - it('ignores the HX-Retarget header when responseTargetPrefersRetargetHeader is false', function () { - htmx.config.responseTargetPrefersRetargetHeader = false; - try { - this.server.respondWith("GET", "/test", [404, { "HX-Retarget": "#d2" }, "Not found!"]); - var btn = make('') - var div1 = make('
    ') - var div2 = make('
    ') - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal("Not found!"); - div2.innerHTML.should.equal(""); - } finally { - htmx.config.responseTargetPrefersRetargetHeader = true; - } - }); - - it('targets the already established target when responseTargetPrefersExisting is true', function () { - htmx.config.responseTargetPrefersExisting = true; - try { - this.server.respondWith("GET", "/test", [404, {}, "Not found!"]); - var btn = make('') - var div1 = make('
    ') - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal(""); - btn.innerHTML.should.equal("Not found!"); - } finally { - htmx.config.responseTargetPrefersExisting = false; - } - }); - - describe('status code formatting', function() - { - var attributes = [ - "hx-target-404", - - "hx-target-40*", - "hx-target-40x", - - "hx-target-4*", - "hx-target-4x", - "hx-target-4**", - "hx-target-4xx", - - "hx-target-*", - "hx-target-x", - "hx-target-***", - "hx-target-xxx", - ]; - - // String replacement because IE11 doesn't support template literals - var btnMarkup = ''; - // forEach because IE11 doesn't play nice with closures inside for loops - attributes.forEach(function(attribute) { - it('supports ' + attribute, function() { - this.server.respondWith("GET", "/test", [404, {}, "Not found!"]); - var btn = make(btnMarkup.replace("HX_TARGET", attribute)); - var div1 = make('
    ') - btn.click(); - this.server.respond(); - div1.innerHTML.should.equal("Not found!"); - }); - }); - }); -}); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/sse.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/sse.js deleted file mode 100644 index ce40601988c..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/sse.js +++ /dev/null @@ -1,301 +0,0 @@ -describe("sse extension", function() { - - function mockEventSource() { - var listeners = {}; - var wasClosed = false; - var url; - var mockEventSource = { - _listeners: listeners, - removeEventListener: function(name, l) { - listeners[name] = listeners[name].filter(function(elt, idx, arr) { - if (arr[idx] === l) { - return false; - } - return true; - }) - }, - addEventListener: function(message, l) { - if (listeners[message] === undefined) { - listeners[message] = []; - } - listeners[message].push(l) - }, - sendEvent: function(eventName, data) { - var eventListeners = listeners[eventName]; - if (eventListeners) { - eventListeners.forEach(function(listener) { - var event = htmx._("makeEvent")(eventName); - event.data = data; - listener(event); - }) - } - }, - close: function() { - wasClosed = true; - }, - wasClosed: function() { - return wasClosed; - }, - connect: function(url) { - this.url = url - } - }; - return mockEventSource; - } - - beforeEach(function() { - this.server = makeServer(); - var eventSource = mockEventSource(); - this.eventSource = eventSource; - clearWorkArea(); - htmx.createEventSource = function(url) { - eventSource.connect(url); - return eventSource; - }; - }); - afterEach(function() { - this.server.restore(); - this.eventSource = mockEventSource(); - clearWorkArea(); - }); - - it('handles basic sse triggering', function() { - - this.server.respondWith("GET", "/d1", "div1 updated"); - this.server.respondWith("GET", "/d2", "div2 updated"); - - var div = make('
    ' + - '
    div1
    ' + - '
    div2
    ' + - '
    '); - - this.eventSource.sendEvent("e1"); - this.server.respond(); - byId("d1").innerHTML.should.equal("div1 updated"); - byId("d2").innerHTML.should.equal("div2"); - - this.eventSource.sendEvent("e2"); - this.server.respond(); - byId("d1").innerHTML.should.equal("div1 updated"); - byId("d2").innerHTML.should.equal("div2 updated"); - }) - - it('does not trigger events that arent named', function() { - - this.server.respondWith("GET", "/d1", "div1 updated"); - - var div = make('
    ' + - '
    div1
    ' + - '
    '); - - this.eventSource.sendEvent("foo"); - this.server.respond(); - byId("d1").innerHTML.should.equal("div1"); - - this.eventSource.sendEvent("e2"); - this.server.respond(); - byId("d1").innerHTML.should.equal("div1"); - - this.eventSource.sendEvent("e1"); - this.server.respond(); - byId("d1").innerHTML.should.equal("div1 updated"); - }) - - it('does not trigger events not on descendents', function() { - - this.server.respondWith("GET", "/d1", "div1 updated"); - - var div = make('
    ' + - '
    div1
    '); - - this.eventSource.sendEvent("foo"); - this.server.respond(); - byId("d1").innerHTML.should.equal("div1"); - - this.eventSource.sendEvent("e2"); - this.server.respond(); - byId("d1").innerHTML.should.equal("div1"); - - this.eventSource.sendEvent("e1"); - this.server.respond(); - byId("d1").innerHTML.should.equal("div1"); - }) - - it('is closed after removal, hx-trigger', function() { - this.server.respondWith("GET", "/test", "Clicked!"); - var div = make('
    ' + - '
    div1
    ' + - '
    '); - div.click(); - this.server.respond(); - this.eventSource.wasClosed().should.equal(true) - }) - - it('is closed after removal, hx-swap', function() { - this.server.respondWith("GET", "/test", "Clicked!"); - var div = make('
    ' + - '
    div1
    ' + - '
    '); - div.click(); - this.server.respond(); - this.eventSource.wasClosed().should.equal(true) - }) - - it('is closed after removal with no close and activity, hx-trigger', function() { - var div = make('
    ' + - '
    div1
    ' + - '
    '); - div.parentElement.removeChild(div); - this.eventSource.sendEvent("e1") - this.eventSource.wasClosed().should.equal(true) - }) - - it('is not listening for events after hx-swap element removed', function() { - var div = make('
    ' + - '
    div1
    ' + - '
    '); - this.eventSource._listeners["e1"].should.be.lengthOf(1) - div.removeChild(byId("d1")); - this.eventSource.sendEvent("e1", "Test") - this.eventSource._listeners["e1"].should.be.empty - }) - - // sse and hx-trigger handlers are distinct - it('is closed after removal with no close and activity, sse-swap', function() { - var div = make('
    ' + - '
    div1
    ' + - '
    '); - div.parentElement.removeChild(div); - this.eventSource.sendEvent("e1") - this.eventSource.wasClosed().should.equal(true) - }) - - it('swaps content properly on SSE swap', function() { - var div = make('
    \n' + - '
    \n' + - '
    \n' + - '
    \n'); - byId("d1").innerText.should.equal("") - byId("d2").innerText.should.equal("") - this.eventSource.sendEvent("e1", "Event 1") - byId("d1").innerText.should.equal("Event 1") - byId("d2").innerText.should.equal("") - this.eventSource.sendEvent("e2", "Event 2") - byId("d1").innerText.should.equal("Event 1") - byId("d2").innerText.should.equal("Event 2") - }) - - it('swaps swapped in content', function() { - var div = make('
    \n' + - '
    \n' + - '
    \n' - ) - - this.eventSource.sendEvent("e1", '
    ') - this.eventSource.sendEvent("e2", 'Event 2') - byId("d2").innerText.should.equal("Event 2") - }) - - it('works in a child of an hx-ext="sse" element', function() { - var div = make('
    \n' + - '
    div1
    \n' + - '
    \n' - ) - this.eventSource.sendEvent("e1", "Event 1") - byId("d1").innerText.should.equal("Event 1") - }) - - it('only adds sseEventSource to elements with sse-connect', function() { - var div = make('
    \n' + - '
    \n' + - '
    '); - - (byId('d1')["htmx-internal-data"].sseEventSource == undefined).should.be.true - - // Even when content is swapped in - this.eventSource.sendEvent("e1", '
    '); - - (byId('d2')["htmx-internal-data"].sseEventSource == undefined).should.be.true - }) - - it('initializes connections in swapped content', function() { - this.server.respondWith("GET", "/d1", '
    div2
    '); - this.server.respondWith("GET", "/d2", "div2 updated"); - - var div = make('
    '); - div.click(); - - this.server.respond(); - this.eventSource.sendEvent("e2"); - this.server.respond(); - - byId("d2").innerHTML.should.equal("div2 updated"); - }) - - it('creates an eventsource on elements with sse-connect', function() { - var div = make('
    '); - - (byId("d1")['htmx-internal-data'].sseEventSource == undefined).should.be.false; - - }) - - it('raises htmx:sseBeforeMessage when receiving message from the server', function () { - var myEventCalled = false; - - function handle(evt) { - myEventCalled = true; - } - - htmx.on("htmx:sseBeforeMessage", handle) - - var div = make('
    '); - - this.eventSource.sendEvent("e1", '
    ') - - myEventCalled.should.be.true; - - htmx.off("htmx:sseBeforeMessage", handle) - }) - - it('cancels swap when htmx:sseBeforeMessage was cancelled', function () { - var myEventCalled = false; - - function handle(evt) { - myEventCalled = true; - evt.preventDefault(); - } - - htmx.on("htmx:sseBeforeMessage", handle) - - var div = make('
    div1
    '); - - this.eventSource.sendEvent("e1", '
    replaced
    ') - - myEventCalled.should.be.true; - - byId("d1").innerHTML.should.equal("div1"); - - htmx.off("htmx:sseBeforeMessage", handle) - }) - - it('raises htmx:sseMessage when message was completely processed', function () { - var myEventCalled = false; - - function handle(evt) { - myEventCalled = true; - } - - htmx.on("htmx:sseMessage", handle) - - var div = make('
    div1
    '); - - this.eventSource.sendEvent("e1", '
    replaced
    ') - - myEventCalled.should.be.true; - byId("d1").innerHTML.should.equal("replaced"); - - htmx.off("htmx:sseMessage", handle) - }) - -}); - diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/ws.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/ws.js deleted file mode 100644 index ce17782d5be..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/ext/ws.js +++ /dev/null @@ -1,818 +0,0 @@ -describe("web-sockets extension", function () { - // mock-socket isn't IE11 compatible, thus this handmade one - // Using the same syntax as the library, so the initial tests didn't require changes to work - // TODO when we get rid of IE11 for htmx2, replace this by mock-socket since it ofc doesn't implement every feature - function mockWebsocket() { - var mockSocketClient = { - addEventListener: function (event, handler) { - var handlers = this._listeners[event] || [] - handlers.push(handler) - this._listeners[event] = handlers - }, - on: function (event, handler) { - this.addEventListener(event, handler) - }, - send: function (data) { - mockSocketServer._fireEvent("message", data) - }, - connect: function () { - this._open = true - mockSocketServer._fireEvent("connection", mockSocketServer) - setTimeout(function () { - this._fireEvent("open", {type: "open"}) - }.bind(this), 2) - }, - close: function () { - if (this._open) { - this._open = false - this._fireEvent("close", {type: "close", code: 0}) - } - }, - _listeners: {}, - _fireEvent: function (event, data) { - var handlers = this._listeners[event] || [] - if (typeof this["on" + event] === "function") { - handlers.push(this["on" + event]) - } - for (var i = 0; i < handlers.length; i++) { - handlers[i](data) - } - }, - _open: false, - } - var mockSocketServer = { - addEventListener: function (event, handler) { - var handlers = this._listeners[event] || [] - handlers.push(handler) - this._listeners[event] = handlers - }, - on: function (event, handler) { - this.addEventListener(event, handler) - }, - close: function () { - mockSocketClient.close() - }, - stop: function () { - }, - emit: function (event, data) { - mockSocketClient._fireEvent(event, {data: data}) - }, - clients: function () { // Replicate old mock-socket syntax to avoid huge file diff to merge - return mockSocketClient._open ? [1] : [] - }, - _listeners: {}, - _fireEvent: function (event, data) { - var handlers = this._listeners[event] || [] - for (var i = 0; i < handlers.length; i++) { - handlers[i](data) - } - }, - } - return { - client: mockSocketClient, - server: mockSocketServer, - } - } - - beforeEach(function () { - this.server = makeServer(); - // this.socketServer = new Mock.Server('ws://localhost:8080'); - var mockedSocket = mockWebsocket(); - this.socketServer = mockedSocket.server; - this.messages = []; - this.clock = sinon.useFakeTimers(); - - this.socketServer.on('connection', function (socket) { - socket.on('message', function (event) { - this.messages.push(event) - }.bind(this)) - }.bind(this)) - - /* Mock socket library is cool, but it uses setTimeout to emulate asynchronous nature of the network. - * To avoid unexpected behavior, make sure to call this method whenever socket would have a network communication, - * e.g., when connecting, disconnecting, sending messages. */ - this.tickMock = function () { - this.clock.tick(5); - } - - clearWorkArea(); - this.oldCreateWebSocket = htmx.createWebSocket; - htmx.createWebSocket = function () { - mockedSocket.client.connect() - return mockedSocket.client - }; - }); - afterEach(function () { - this.server.restore(); - clearWorkArea(); - this.socketServer.close(); - this.socketServer.stop(); - this.clock.restore(); - htmx.createWebSocket = this.oldCreateWebSocket; - }); - - it('can establish connection with the server', function () { - this.socketServer.clients().length.should.equal(0); - make('
    '); - this.socketServer.clients().length.should.equal(1); - - this.tickMock(); - }) - - it('is closed after removal by swap', function () { - this.server.respondWith("GET", "/test", "Clicked!"); - - var div = make('
    '); - this.tickMock(); - - this.socketServer.clients().length.should.equal(1); - - div.click(); - this.server.respond(); - - this.tickMock(); - - this.socketServer.clients().length.should.equal(0); - }) - - it('is closed after removal by js when message is received', function () { - this.server.respondWith("GET", "/test", "Clicked!"); - - var div = make('
    '); - this.tickMock(); - - this.socketServer.clients().length.should.equal(1); - div.parentElement.removeChild(div); - - this.socketServer.emit('message', 'foo'); - this.tickMock(); - - this.socketServer.clients().length.should.equal(0); - }) - - it('sends data to the server', function () { - var div = make('
    div1
    '); - this.tickMock(); - - byId("d1").click(); - - this.tickMock(); - - this.messages.length.should.equal(1); - }) - - it('sends data to the server with specific trigger', function () { - var div = make('
    div1
    '); - this.tickMock(); - - byId("d1").click(); - - this.tickMock(); - - this.messages.length.should.equal(1); - }) - - it('sends data to the server with polling trigger', function () { - var div = make('
    div1
    '); - this.tickMock(); - this.clock.tick(2000); - - byId("d1").click(); - - this.tickMock(); - - this.messages.length.should.equal(2); - }) - - it('sends expected headers to the server', function () { - var div = make('
    '); - this.tickMock(); - - byId("d1").click(); - - this.tickMock(); - - this.messages.length.should.equal(1); - var message = JSON.parse(this.messages[0]); - var headers = message.HEADERS; - - console.log(headers); - - headers['HX-Request'].should.be.equal('true'); - headers['HX-Current-URL'].should.be.equal(document.location.href) - headers['HX-Trigger'].should.be.equal('d1'); - headers['HX-Trigger-Name'].should.be.equal('d1-name'); - headers['HX-Target'].should.be.equal('target'); - }) - - it('handles message from the server', function () { - var div = make('
    div1
    div2
    '); - this.tickMock(); - - this.socketServer.emit('message', "
    replaced
    "); - - this.tickMock(); - byId("d1").innerHTML.should.equal("replaced"); - byId("d2").innerHTML.should.equal("div2"); - }) - - it('raises lifecycle events (connecting, open, close) in correct order', function () { - var handledEventTypes = []; - var handler = function (evt) { handledEventTypes.push(evt.detail.event.type) }; - - htmx.on("htmx:wsConnecting", handler); - - var div = make('
    '); - - htmx.on(div, "htmx:wsOpen", handler); - htmx.on(div, "htmx:wsClose", handler); - - this.tickMock(); - - div.parentElement.removeChild(div); - this.socketServer.emit('message', 'foo'); - - this.tickMock(); - - handledEventTypes.should.eql(['connecting', 'open', 'close']); - - this.tickMock(); - - htmx.off("htmx:wsConnecting", handler); - htmx.off(div, "htmx:wsOpen", handler); - htmx.off(div, "htmx:wsClose", handler); - }) - - it('raises htmx:wsConfigSend when sending, allows message modification', function () { - var myEventCalled = false; - - function handle(evt) { - myEventCalled = true; - evt.detail.parameters.foo = "bar"; - } - - htmx.on("htmx:wsConfigSend", handle) - - var div = make('
    div1
    '); - this.tickMock(); - - byId("d1").click(); - - this.tickMock(); - - myEventCalled.should.be.true; - this.messages.length.should.equal(1); - this.messages[0].should.contains('"foo":"bar"') - htmx.off("htmx:wsConfigSend", handle) - }) - - it('passes socketWrapper to htmx:wsConfigSend', function () { - var socketWrapper = null; - - function handle(evt) { - evt.preventDefault(); - socketWrapper = evt.detail.socketWrapper; - socketWrapper.send(JSON.stringify({foo: 'bar'}), evt.detail.elt) - } - - htmx.on("htmx:wsConfigSend", handle) - - var div = make('
    div1
    '); - this.tickMock(); - - byId("d1").click(); - - this.tickMock(); - - socketWrapper.should.not.be.null; - socketWrapper.send.should.be.a('function'); - socketWrapper.sendImmediately.should.be.a('function'); - socketWrapper.queue.should.be.an('array'); - - this.messages.length.should.equal(1); - this.messages[0].should.contains('"foo":"bar"') - - htmx.off("htmx:wsConfigSend", handle); - }) - - it('cancels sending when htmx:wsConfigSend is cancelled', function () { - var myEventCalled = false; - - function handle(evt) { - myEventCalled = true; - evt.preventDefault(); - } - - htmx.on("htmx:wsConfigSend", handle) - - var div = make('
    div1
    '); - this.tickMock(); - - byId("d1").click(); - - this.messages.length.should.equal(0); - - myEventCalled.should.be.true; - - htmx.off("htmx:wsConfigSend", handle); - }) - - it('raises htmx:wsBeforeSend when sending', function () { - var myEventCalled = false; - - function handle(evt) { - myEventCalled = true; - } - - htmx.on("htmx:wsBeforeSend", handle) - - var div = make('
    div1
    '); - this.tickMock(); - - byId("d1").click(); - - this.tickMock(); - - myEventCalled.should.be.true; - this.messages.length.should.equal(1); - htmx.off("htmx:wsBeforeSend", handle) - }) - - it('cancels sending when htmx:wsBeforeSend is cancelled', function () { - var myEventCalled = false; - - function handle(evt) { - myEventCalled = true; - evt.preventDefault(); - } - - htmx.on("htmx:wsBeforeSend", handle) - - var div = make('
    div1
    '); - this.tickMock(); - - byId("d1").click(); - - this.tickMock(); - - myEventCalled.should.be.true; - this.messages.length.should.equal(0); - htmx.off("htmx:wsBeforeSend", handle) - }) - - it('raises htmx:wsAfterSend when sending', function () { - var myEventCalled = false; - - function handle(evt) { - myEventCalled = true; - } - - htmx.on("htmx:wsAfterSend", handle) - - var div = make('
    div1
    '); - this.tickMock(); - - byId("d1").click(); - - this.tickMock(); - - myEventCalled.should.be.true; - this.messages.length.should.equal(1); - htmx.off("htmx:wsAfterSend", handle) - }) - - it('raises htmx:wsBeforeMessage when receiving message from the server', function () { - var myEventCalled = false; - - function handle(evt) { - myEventCalled = true; - } - - htmx.on("htmx:wsBeforeMessage", handle) - - var div = make('
    div1
    div2
    '); - this.tickMock(); - - this.socketServer.emit('message', "
    replaced
    ") - - this.tickMock(); - myEventCalled.should.be.true; - - htmx.off("htmx:wsBeforeMessage", handle) - }) - - it('cancels swap when htmx:wsBeforeMessage was cancelled', function () { - var myEventCalled = false; - - function handle(evt) { - myEventCalled = true; - evt.preventDefault(); - } - - htmx.on("htmx:wsBeforeMessage", handle) - - var div = make('
    div1
    div2
    '); - this.tickMock(); - - this.socketServer.emit('message', "
    replaced
    ") - - this.tickMock(); - myEventCalled.should.be.true; - - byId("d1").innerHTML.should.equal("div1"); - byId("d2").innerHTML.should.equal("div2"); - - htmx.off("htmx:wsBeforeMessage", handle) - }) - - it('raises htmx:wsAfterMessage when message was completely processed', function () { - var myEventCalled = false; - - function handle(evt) { - myEventCalled = true; - } - - htmx.on("htmx:wsAfterMessage", handle) - - var div = make('
    div1
    div2
    '); - this.tickMock(); - - this.socketServer.emit('message', "
    replaced
    ") - - this.tickMock(); - myEventCalled.should.be.true; - - htmx.off("htmx:wsAfterMessage", handle) - }) - - it('sends data to the server with non-htmx form + submit button & value', function () { - make('' + - '' + - '' + - '' + - ''); - this.tickMock(); - - byId("b1").click(); - - this.tickMock(); - - this.messages.length.should.equal(1); - this.messages[0].should.contains('"foo":"bar"') - this.messages[0].should.contains('"action":"A"') - - byId("b2").click(); - - this.tickMock(); - - this.messages.length.should.equal(2); - this.messages[1].should.contains('"foo":"bar"') - this.messages[1].should.contains('"action":"B"') - }) - - it('sends data to the server with non-htmx form + submit input & value', function () { - make('
    ' + - '' + - '' + - '' + - '
    '); - this.tickMock(); - - byId("b1").click(); - - this.tickMock(); - - this.messages.length.should.equal(1); - this.messages[0].should.contains('"foo":"bar"') - this.messages[0].should.contains('"action":"A"') - - byId("b2").click(); - - this.tickMock(); - - this.messages.length.should.equal(2); - this.messages[1].should.contains('"foo":"bar"') - this.messages[1].should.contains('"action":"B"') - }) - - it('sends data to the server with child non-htmx form + submit button & value', function () { - make('
    ' + - '
    ' + - '' + - '' + - '' + - '
    ' + - '
    '); - this.tickMock(); - - byId("b1").click(); - - this.tickMock(); - - this.messages.length.should.equal(1); - this.messages[0].should.contains('"foo":"bar"') - this.messages[0].should.contains('"action":"A"') - - byId("b2").click(); - - this.tickMock(); - - this.messages.length.should.equal(2); - this.messages[1].should.contains('"foo":"bar"') - this.messages[1].should.contains('"action":"B"') - }) - - it('sends data to the server with child non-htmx form + submit input & value', function () { - make('
    ' + - '
    ' + - '' + - '' + - '' + - '
    ' + - '
    '); - this.tickMock(); - - byId("b1").click(); - - this.tickMock(); - - this.messages.length.should.equal(1); - this.messages[0].should.contains('"foo":"bar"') - this.messages[0].should.contains('"action":"A"') - - byId("b2").click(); - - this.tickMock(); - - this.messages.length.should.equal(2); - this.messages[1].should.contains('"foo":"bar"') - this.messages[1].should.contains('"action":"B"') - }) - - it('sends data to the server with external non-htmx form + submit button & value', function () { - if (!supportsFormAttribute()) { - this._runnable.title += " - Skipped as IE11 doesn't support form attribute" - this.skip() - return - } - - make('
    ' + - '
    ' + - '' + - '
    ' + - '
    ' + - '' + - ''); - this.tickMock(); - - byId("b1").click(); - - this.tickMock(); - - this.messages.length.should.equal(1); - this.messages[0].should.contains('"foo":"bar"') - this.messages[0].should.contains('"action":"A"') - - byId("b2").click(); - - this.tickMock(); - - this.messages.length.should.equal(2); - this.messages[1].should.contains('"foo":"bar"') - this.messages[1].should.contains('"action":"B"') - }) - - it('sends data to the server with external non-htmx form + submit input & value', function () { - if (!supportsFormAttribute()) { - this._runnable.title += " - Skipped as IE11 doesn't support form attribute" - this.skip() - return - } - - make('
    ' + - '
    ' + - '' + - '
    ' + - '
    ' + - '' + - ''); - this.tickMock(); - - byId("b1").click(); - - this.tickMock(); - - this.messages.length.should.equal(1); - this.messages[0].should.contains('"foo":"bar"') - this.messages[0].should.contains('"action":"A"') - - byId("b2").click(); - - this.tickMock(); - - this.messages.length.should.equal(2); - this.messages[1].should.contains('"foo":"bar"') - this.messages[1].should.contains('"action":"B"') - }) - - describe("Send immediately", function() { - function checkCallForWsBeforeSend(spy, wrapper, message, target) { - // Utility function to always check the same for htmx:wsBeforeSend caught by a spy - spy.calledOnce.should.be.true; - var call = spy.getCall(0); - call.args.length.should.equal(1); - var arg = call.args[0]; - arg.target.should.equal(target); - arg.detail.socketWrapper.should.equal(wrapper); - arg.detail.message.should.equal(message); - } - it('triggers wsBeforeSend on body if provided to sendImmediately', function (done) { - var myEventCalled = sinon.spy(); - var message = '{"foo":"bar"}'; - var handler = function(e){ - var socketWrapper = e.detail.socketWrapper; - window.document.body.addEventListener("htmx:wsBeforeSend", myEventCalled) - try { - socketWrapper.sendImmediately(message, window.document.body) - checkCallForWsBeforeSend(myEventCalled, socketWrapper, message, window.document.body) - } finally { - window.document.body.removeEventListener("htmx:wsBeforeSend", myEventCalled) - } - done() - } - try { - window.document.addEventListener("htmx:wsOpen", handler) - - var div = make('
    div1
    '); - this.tickMock(); - } finally { - window.document.removeEventListener("htmx:wsOpen", handler) - } - - }) - it('triggers wsBeforeSend on any send element provided to sendImmediately', function (done) { - var myEventCalled = sinon.spy(); - var message = '{"a":"b"}'; - var handler = function(e){ - var socketWrapper = e.detail.socketWrapper; - var id1 = byId("d1"); - id1.addEventListener("htmx:wsBeforeSend", myEventCalled) - try { - socketWrapper.sendImmediately(message, d1) - checkCallForWsBeforeSend(myEventCalled, socketWrapper, message, d1) - } finally { - id1.removeEventListener("htmx:wsBeforeSend", myEventCalled) - } - done() - } - - window.document.addEventListener("htmx:wsOpen", handler) - try { - var div = make('
    div1
    '); - this.tickMock(); - } finally { - window.document.removeEventListener("htmx:wsOpen", handler) - } - - }) - it('triggers wsAfterSend on body if provided to sendImmediately', function (done) { - var myEventCalled = sinon.spy(); - var message = '{"foo":"bar"}'; - var handler = function(e){ - var socketWrapper = e.detail.socketWrapper; - window.document.body.addEventListener("htmx:wsAfterSend", myEventCalled) - try { - socketWrapper.sendImmediately(message, window.document.body) - checkCallForWsBeforeSend(myEventCalled, socketWrapper, message, window.document.body) - } finally { - window.document.body.removeEventListener("htmx:wsAfterSend", myEventCalled) - } - done() - } - try { - window.document.addEventListener("htmx:wsOpen", handler) - - var div = make('
    div1
    '); - this.tickMock(); - } finally { - window.document.removeEventListener("htmx:wsOpen", handler) - } - - }) - it('triggers wsAfterSend on any send element provided to sendImmediately', function (done) { - var myEventCalled = sinon.spy(); - var message = '{"a":"b"}'; - var handler = function(e){ - var socketWrapper = e.detail.socketWrapper; - var id1 = byId("d1"); - id1.addEventListener("htmx:wsAfterSend", myEventCalled) - try { - socketWrapper.sendImmediately(message, d1) - checkCallForWsBeforeSend(myEventCalled, socketWrapper, message, d1) - } finally { - id1.removeEventListener("htmx:wsAfterSend", myEventCalled) - } - done() - } - - window.document.addEventListener("htmx:wsOpen", handler) - try { - var div = make('
    div1
    '); - this.tickMock(); - } finally { - window.document.removeEventListener("htmx:wsOpen", handler) - } - - }) - it('sends message if event is not prevented', function (done) { - var message = '{"a":"b"}'; - var noop = function() {} - var handler = function(e){ - var socketWrapper = e.detail.socketWrapper; - var id1 = byId("d1"); - id1.addEventListener("htmx:wsBeforeSend", noop) - try { - socketWrapper.sendImmediately(message, d1) - this.tickMock(); - this.messages.should.eql([message]) - } finally { - id1.removeEventListener("htmx:wsBeforeSend", noop) - } - done() - }.bind(this) - - window.document.addEventListener("htmx:wsOpen", handler) - try { - var div = make('
    div1
    '); - this.tickMock(); - } finally { - window.document.removeEventListener("htmx:wsOpen", handler) - } - }) - it('sends message if no sending element is provided', function (done) { - var message = '{"a":"b"}'; - var handler = function(e){ - var socketWrapper = e.detail.socketWrapper; - socketWrapper.sendImmediately(message) - this.tickMock(); - this.messages.should.eql([message]) - done() - }.bind(this) - - window.document.addEventListener("htmx:wsOpen", handler) - try { - var div = make('
    div1
    '); - this.tickMock(); - } finally { - window.document.removeEventListener("htmx:wsOpen", handler) - } - }) - it('sends message if sending element has no event listener for beforeSend', function (done) { - var message = '{"a":"b"}'; - var handler = function(e){ - var socketWrapper = e.detail.socketWrapper; - var d1 = byId("d1"); - socketWrapper.sendImmediately(message, d1) - this.tickMock(); - this.messages.should.eql([message]) - done() - }.bind(this) - - window.document.addEventListener("htmx:wsOpen", handler) - try { - var div = make('
    div1
    '); - this.tickMock(); - } finally { - window.document.removeEventListener("htmx:wsOpen", handler) - } - }) - it('does not send message if beforeSend is prevented', function (done) { - var message = '{"a":"b"}'; - var eventPrevented = function(e) {e.preventDefault()} - var handler = function(e){ - var socketWrapper = e.detail.socketWrapper; - var id1 = byId("d1"); - id1.addEventListener("htmx:wsBeforeSend", eventPrevented) - try { - socketWrapper.sendImmediately(message, d1) - this.tickMock(); - this.messages.should.eql([]) - } finally { - id1.removeEventListener("htmx:wsBeforeSend", eventPrevented) - } - done() - }.bind(this) - - window.document.addEventListener("htmx:wsOpen", handler) - try { - var div = make('
    div1
    '); - this.tickMock(); - } finally { - window.document.removeEventListener("htmx:wsOpen", handler) - } - - }) - }) - - -}); diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/index.html b/src/test/resources/libraries/htmx/htmx-1.9.11/test/index.html deleted file mode 100644 index fc4141b7441..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/index.html +++ /dev/null @@ -1,186 +0,0 @@ - - - - Mocha Tests - - - - - - - - - - - -

    htmx.js test suite

    -

    Version: 

    - -

    Scratch Page

    - - -

    Manual Tests

    -Here - -

    Mocha Test Suite

    -[ALL] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - - -Work Area -
    -
    -
    - - diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/lib/handlebars-v4.7.6.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/lib/handlebars-v4.7.6.js deleted file mode 100644 index 05d9f6141a6..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/lib/handlebars-v4.7.6.js +++ /dev/null @@ -1,5210 +0,0 @@ -/**! - - @license - handlebars v4.7.6 - -Copyright (C) 2011-2019 by Yehuda Katz - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*/ -(function webpackUniversalModuleDefinition(root, factory) { - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(); - else if(typeof define === 'function' && define.amd) - define([], factory); - else if(typeof exports === 'object') - exports["Handlebars"] = factory(); - else - root["Handlebars"] = factory(); -})(this, function() { -return /******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; - -/******/ // The require function -/******/ function __webpack_require__(moduleId) { - -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) -/******/ return installedModules[moduleId].exports; - -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ exports: {}, -/******/ id: moduleId, -/******/ loaded: false -/******/ }; - -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); - -/******/ // Flag the module as loaded -/******/ module.loaded = true; - -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } - - -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; - -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; - -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; - -/******/ // Load entry module and return exports -/******/ return __webpack_require__(0); -/******/ }) -/************************************************************************/ -/******/ ([ -/* 0 */ -/***/ (function(module, exports, __webpack_require__) { - - 'use strict'; - - var _interopRequireDefault = __webpack_require__(1)['default']; - - exports.__esModule = true; - - var _handlebarsRuntime = __webpack_require__(2); - - var _handlebarsRuntime2 = _interopRequireDefault(_handlebarsRuntime); - - // Compiler imports - - var _handlebarsCompilerAst = __webpack_require__(45); - - var _handlebarsCompilerAst2 = _interopRequireDefault(_handlebarsCompilerAst); - - var _handlebarsCompilerBase = __webpack_require__(46); - - var _handlebarsCompilerCompiler = __webpack_require__(51); - - var _handlebarsCompilerJavascriptCompiler = __webpack_require__(52); - - var _handlebarsCompilerJavascriptCompiler2 = _interopRequireDefault(_handlebarsCompilerJavascriptCompiler); - - var _handlebarsCompilerVisitor = __webpack_require__(49); - - var _handlebarsCompilerVisitor2 = _interopRequireDefault(_handlebarsCompilerVisitor); - - var _handlebarsNoConflict = __webpack_require__(44); - - var _handlebarsNoConflict2 = _interopRequireDefault(_handlebarsNoConflict); - - var _create = _handlebarsRuntime2['default'].create; - function create() { - var hb = _create(); - - hb.compile = function (input, options) { - return _handlebarsCompilerCompiler.compile(input, options, hb); - }; - hb.precompile = function (input, options) { - return _handlebarsCompilerCompiler.precompile(input, options, hb); - }; - - hb.AST = _handlebarsCompilerAst2['default']; - hb.Compiler = _handlebarsCompilerCompiler.Compiler; - hb.JavaScriptCompiler = _handlebarsCompilerJavascriptCompiler2['default']; - hb.Parser = _handlebarsCompilerBase.parser; - hb.parse = _handlebarsCompilerBase.parse; - hb.parseWithoutProcessing = _handlebarsCompilerBase.parseWithoutProcessing; - - return hb; - } - - var inst = create(); - inst.create = create; - - _handlebarsNoConflict2['default'](inst); - - inst.Visitor = _handlebarsCompilerVisitor2['default']; - - inst['default'] = inst; - - exports['default'] = inst; - module.exports = exports['default']; - -/***/ }), -/* 1 */ -/***/ (function(module, exports) { - - "use strict"; - - exports["default"] = function (obj) { - return obj && obj.__esModule ? obj : { - "default": obj - }; - }; - - exports.__esModule = true; - -/***/ }), -/* 2 */ -/***/ (function(module, exports, __webpack_require__) { - - 'use strict'; - - var _interopRequireWildcard = __webpack_require__(3)['default']; - - var _interopRequireDefault = __webpack_require__(1)['default']; - - exports.__esModule = true; - - var _handlebarsBase = __webpack_require__(4); - - var base = _interopRequireWildcard(_handlebarsBase); - - // Each of these augment the Handlebars object. No need to setup here. - // (This is done to easily share code between commonjs and browse envs) - - var _handlebarsSafeString = __webpack_require__(37); - - var _handlebarsSafeString2 = _interopRequireDefault(_handlebarsSafeString); - - var _handlebarsException = __webpack_require__(6); - - var _handlebarsException2 = _interopRequireDefault(_handlebarsException); - - var _handlebarsUtils = __webpack_require__(5); - - var Utils = _interopRequireWildcard(_handlebarsUtils); - - var _handlebarsRuntime = __webpack_require__(38); - - var runtime = _interopRequireWildcard(_handlebarsRuntime); - - var _handlebarsNoConflict = __webpack_require__(44); - - var _handlebarsNoConflict2 = _interopRequireDefault(_handlebarsNoConflict); - - // For compatibility and usage outside of module systems, make the Handlebars object a namespace - function create() { - var hb = new base.HandlebarsEnvironment(); - - Utils.extend(hb, base); - hb.SafeString = _handlebarsSafeString2['default']; - hb.Exception = _handlebarsException2['default']; - hb.Utils = Utils; - hb.escapeExpression = Utils.escapeExpression; - - hb.VM = runtime; - hb.template = function (spec) { - return runtime.template(spec, hb); - }; - - return hb; - } - - var inst = create(); - inst.create = create; - - _handlebarsNoConflict2['default'](inst); - - inst['default'] = inst; - - exports['default'] = inst; - module.exports = exports['default']; - -/***/ }), -/* 3 */ -/***/ (function(module, exports) { - - "use strict"; - - exports["default"] = function (obj) { - if (obj && obj.__esModule) { - return obj; - } else { - var newObj = {}; - - if (obj != null) { - for (var key in obj) { - if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; - } - } - - newObj["default"] = obj; - return newObj; - } - }; - - exports.__esModule = true; - -/***/ }), -/* 4 */ -/***/ (function(module, exports, __webpack_require__) { - - 'use strict'; - - var _interopRequireDefault = __webpack_require__(1)['default']; - - exports.__esModule = true; - exports.HandlebarsEnvironment = HandlebarsEnvironment; - - var _utils = __webpack_require__(5); - - var _exception = __webpack_require__(6); - - var _exception2 = _interopRequireDefault(_exception); - - var _helpers = __webpack_require__(10); - - var _decorators = __webpack_require__(30); - - var _logger = __webpack_require__(32); - - var _logger2 = _interopRequireDefault(_logger); - - var _internalProtoAccess = __webpack_require__(33); - - var VERSION = '4.7.6'; - exports.VERSION = VERSION; - var COMPILER_REVISION = 8; - exports.COMPILER_REVISION = COMPILER_REVISION; - var LAST_COMPATIBLE_COMPILER_REVISION = 7; - - exports.LAST_COMPATIBLE_COMPILER_REVISION = LAST_COMPATIBLE_COMPILER_REVISION; - var REVISION_CHANGES = { - 1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it - 2: '== 1.0.0-rc.3', - 3: '== 1.0.0-rc.4', - 4: '== 1.x.x', - 5: '== 2.0.0-alpha.x', - 6: '>= 2.0.0-beta.1', - 7: '>= 4.0.0 <4.3.0', - 8: '>= 4.3.0' - }; - - exports.REVISION_CHANGES = REVISION_CHANGES; - var objectType = '[object Object]'; - - function HandlebarsEnvironment(helpers, partials, decorators) { - this.helpers = helpers || {}; - this.partials = partials || {}; - this.decorators = decorators || {}; - - _helpers.registerDefaultHelpers(this); - _decorators.registerDefaultDecorators(this); - } - - HandlebarsEnvironment.prototype = { - constructor: HandlebarsEnvironment, - - logger: _logger2['default'], - log: _logger2['default'].log, - - registerHelper: function registerHelper(name, fn) { - if (_utils.toString.call(name) === objectType) { - if (fn) { - throw new _exception2['default']('Arg not supported with multiple helpers'); - } - _utils.extend(this.helpers, name); - } else { - this.helpers[name] = fn; - } - }, - unregisterHelper: function unregisterHelper(name) { - delete this.helpers[name]; - }, - - registerPartial: function registerPartial(name, partial) { - if (_utils.toString.call(name) === objectType) { - _utils.extend(this.partials, name); - } else { - if (typeof partial === 'undefined') { - throw new _exception2['default']('Attempting to register a partial called "' + name + '" as undefined'); - } - this.partials[name] = partial; - } - }, - unregisterPartial: function unregisterPartial(name) { - delete this.partials[name]; - }, - - registerDecorator: function registerDecorator(name, fn) { - if (_utils.toString.call(name) === objectType) { - if (fn) { - throw new _exception2['default']('Arg not supported with multiple decorators'); - } - _utils.extend(this.decorators, name); - } else { - this.decorators[name] = fn; - } - }, - unregisterDecorator: function unregisterDecorator(name) { - delete this.decorators[name]; - }, - /** - * Reset the memory of illegal property accesses that have already been logged. - * @deprecated should only be used in handlebars test-cases - */ - resetLoggedPropertyAccesses: function resetLoggedPropertyAccesses() { - _internalProtoAccess.resetLoggedProperties(); - } - }; - - var log = _logger2['default'].log; - - exports.log = log; - exports.createFrame = _utils.createFrame; - exports.logger = _logger2['default']; - -/***/ }), -/* 5 */ -/***/ (function(module, exports) { - - 'use strict'; - - exports.__esModule = true; - exports.extend = extend; - exports.indexOf = indexOf; - exports.escapeExpression = escapeExpression; - exports.isEmpty = isEmpty; - exports.createFrame = createFrame; - exports.blockParams = blockParams; - exports.appendContextPath = appendContextPath; - var escape = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''', - '`': '`', - '=': '=' - }; - - var badChars = /[&<>"'`=]/g, - possible = /[&<>"'`=]/; - - function escapeChar(chr) { - return escape[chr]; - } - - function extend(obj /* , ...source */) { - for (var i = 1; i < arguments.length; i++) { - for (var key in arguments[i]) { - if (Object.prototype.hasOwnProperty.call(arguments[i], key)) { - obj[key] = arguments[i][key]; - } - } - } - - return obj; - } - - var toString = Object.prototype.toString; - - exports.toString = toString; - // Sourced from lodash - // https://github.com/bestiejs/lodash/blob/master/LICENSE.txt - /* eslint-disable func-style */ - var isFunction = function isFunction(value) { - return typeof value === 'function'; - }; - // fallback for older versions of Chrome and Safari - /* istanbul ignore next */ - if (isFunction(/x/)) { - exports.isFunction = isFunction = function (value) { - return typeof value === 'function' && toString.call(value) === '[object Function]'; - }; - } - exports.isFunction = isFunction; - - /* eslint-enable func-style */ - - /* istanbul ignore next */ - var isArray = Array.isArray || function (value) { - return value && typeof value === 'object' ? toString.call(value) === '[object Array]' : false; - }; - - exports.isArray = isArray; - // Older IE versions do not directly support indexOf so we must implement our own, sadly. - - function indexOf(array, value) { - for (var i = 0, len = array.length; i < len; i++) { - if (array[i] === value) { - return i; - } - } - return -1; - } - - function escapeExpression(string) { - if (typeof string !== 'string') { - // don't escape SafeStrings, since they're already safe - if (string && string.toHTML) { - return string.toHTML(); - } else if (string == null) { - return ''; - } else if (!string) { - return string + ''; - } - - // Force a string conversion as this will be done by the append regardless and - // the regex test will do this transparently behind the scenes, causing issues if - // an object's to string has escaped characters in it. - string = '' + string; - } - - if (!possible.test(string)) { - return string; - } - return string.replace(badChars, escapeChar); - } - - function isEmpty(value) { - if (!value && value !== 0) { - return true; - } else if (isArray(value) && value.length === 0) { - return true; - } else { - return false; - } - } - - function createFrame(object) { - var frame = extend({}, object); - frame._parent = object; - return frame; - } - - function blockParams(params, ids) { - params.path = ids; - return params; - } - - function appendContextPath(contextPath, id) { - return (contextPath ? contextPath + '.' : '') + id; - } - -/***/ }), -/* 6 */ -/***/ (function(module, exports, __webpack_require__) { - - 'use strict'; - - var _Object$defineProperty = __webpack_require__(7)['default']; - - exports.__esModule = true; - var errorProps = ['description', 'fileName', 'lineNumber', 'endLineNumber', 'message', 'name', 'number', 'stack']; - - function Exception(message, node) { - var loc = node && node.loc, - line = undefined, - endLineNumber = undefined, - column = undefined, - endColumn = undefined; - - if (loc) { - line = loc.start.line; - endLineNumber = loc.end.line; - column = loc.start.column; - endColumn = loc.end.column; - - message += ' - ' + line + ':' + column; - } - - var tmp = Error.prototype.constructor.call(this, message); - - // Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work. - for (var idx = 0; idx < errorProps.length; idx++) { - this[errorProps[idx]] = tmp[errorProps[idx]]; - } - - /* istanbul ignore else */ - if (Error.captureStackTrace) { - Error.captureStackTrace(this, Exception); - } - - try { - if (loc) { - this.lineNumber = line; - this.endLineNumber = endLineNumber; - - // Work around issue under safari where we can't directly set the column value - /* istanbul ignore next */ - if (_Object$defineProperty) { - Object.defineProperty(this, 'column', { - value: column, - enumerable: true - }); - Object.defineProperty(this, 'endColumn', { - value: endColumn, - enumerable: true - }); - } else { - this.column = column; - this.endColumn = endColumn; - } - } - } catch (nop) { - /* Ignore if the browser is very particular */ - } - } - - Exception.prototype = new Error(); - - exports['default'] = Exception; - module.exports = exports['default']; - -/***/ }), -/* 7 */ -/***/ (function(module, exports, __webpack_require__) { - - module.exports = { "default": __webpack_require__(8), __esModule: true }; - -/***/ }), -/* 8 */ -/***/ (function(module, exports, __webpack_require__) { - - var $ = __webpack_require__(9); - module.exports = function defineProperty(it, key, desc){ - return $.setDesc(it, key, desc); - }; - -/***/ }), -/* 9 */ -/***/ (function(module, exports) { - - var $Object = Object; - module.exports = { - create: $Object.create, - getProto: $Object.getPrototypeOf, - isEnum: {}.propertyIsEnumerable, - getDesc: $Object.getOwnPropertyDescriptor, - setDesc: $Object.defineProperty, - setDescs: $Object.defineProperties, - getKeys: $Object.keys, - getNames: $Object.getOwnPropertyNames, - getSymbols: $Object.getOwnPropertySymbols, - each: [].forEach - }; - -/***/ }), -/* 10 */ -/***/ (function(module, exports, __webpack_require__) { - - 'use strict'; - - var _interopRequireDefault = __webpack_require__(1)['default']; - - exports.__esModule = true; - exports.registerDefaultHelpers = registerDefaultHelpers; - exports.moveHelperToHooks = moveHelperToHooks; - - var _helpersBlockHelperMissing = __webpack_require__(11); - - var _helpersBlockHelperMissing2 = _interopRequireDefault(_helpersBlockHelperMissing); - - var _helpersEach = __webpack_require__(12); - - var _helpersEach2 = _interopRequireDefault(_helpersEach); - - var _helpersHelperMissing = __webpack_require__(25); - - var _helpersHelperMissing2 = _interopRequireDefault(_helpersHelperMissing); - - var _helpersIf = __webpack_require__(26); - - var _helpersIf2 = _interopRequireDefault(_helpersIf); - - var _helpersLog = __webpack_require__(27); - - var _helpersLog2 = _interopRequireDefault(_helpersLog); - - var _helpersLookup = __webpack_require__(28); - - var _helpersLookup2 = _interopRequireDefault(_helpersLookup); - - var _helpersWith = __webpack_require__(29); - - var _helpersWith2 = _interopRequireDefault(_helpersWith); - - function registerDefaultHelpers(instance) { - _helpersBlockHelperMissing2['default'](instance); - _helpersEach2['default'](instance); - _helpersHelperMissing2['default'](instance); - _helpersIf2['default'](instance); - _helpersLog2['default'](instance); - _helpersLookup2['default'](instance); - _helpersWith2['default'](instance); - } - - function moveHelperToHooks(instance, helperName, keepHelper) { - if (instance.helpers[helperName]) { - instance.hooks[helperName] = instance.helpers[helperName]; - if (!keepHelper) { - delete instance.helpers[helperName]; - } - } - } - -/***/ }), -/* 11 */ -/***/ (function(module, exports, __webpack_require__) { - - 'use strict'; - - exports.__esModule = true; - - var _utils = __webpack_require__(5); - - exports['default'] = function (instance) { - instance.registerHelper('blockHelperMissing', function (context, options) { - var inverse = options.inverse, - fn = options.fn; - - if (context === true) { - return fn(this); - } else if (context === false || context == null) { - return inverse(this); - } else if (_utils.isArray(context)) { - if (context.length > 0) { - if (options.ids) { - options.ids = [options.name]; - } - - return instance.helpers.each(context, options); - } else { - return inverse(this); - } - } else { - if (options.data && options.ids) { - var data = _utils.createFrame(options.data); - data.contextPath = _utils.appendContextPath(options.data.contextPath, options.name); - options = { data: data }; - } - - return fn(context, options); - } - }); - }; - - module.exports = exports['default']; - -/***/ }), -/* 12 */ -/***/ (function(module, exports, __webpack_require__) { - - /* WEBPACK VAR INJECTION */(function(global) {'use strict'; - - var _Object$keys = __webpack_require__(13)['default']; - - var _interopRequireDefault = __webpack_require__(1)['default']; - - exports.__esModule = true; - - var _utils = __webpack_require__(5); - - var _exception = __webpack_require__(6); - - var _exception2 = _interopRequireDefault(_exception); - - exports['default'] = function (instance) { - instance.registerHelper('each', function (context, options) { - if (!options) { - throw new _exception2['default']('Must pass iterator to #each'); - } - - var fn = options.fn, - inverse = options.inverse, - i = 0, - ret = '', - data = undefined, - contextPath = undefined; - - if (options.data && options.ids) { - contextPath = _utils.appendContextPath(options.data.contextPath, options.ids[0]) + '.'; - } - - if (_utils.isFunction(context)) { - context = context.call(this); - } - - if (options.data) { - data = _utils.createFrame(options.data); - } - - function execIteration(field, index, last) { - if (data) { - data.key = field; - data.index = index; - data.first = index === 0; - data.last = !!last; - - if (contextPath) { - data.contextPath = contextPath + field; - } - } - - ret = ret + fn(context[field], { - data: data, - blockParams: _utils.blockParams([context[field], field], [contextPath + field, null]) - }); - } - - if (context && typeof context === 'object') { - if (_utils.isArray(context)) { - for (var j = context.length; i < j; i++) { - if (i in context) { - execIteration(i, i, i === context.length - 1); - } - } - } else if (global.Symbol && context[global.Symbol.iterator]) { - var newContext = []; - var iterator = context[global.Symbol.iterator](); - for (var it = iterator.next(); !it.done; it = iterator.next()) { - newContext.push(it.value); - } - context = newContext; - for (var j = context.length; i < j; i++) { - execIteration(i, i, i === context.length - 1); - } - } else { - (function () { - var priorKey = undefined; - - _Object$keys(context).forEach(function (key) { - // We're running the iterations one step out of sync so we can detect - // the last iteration without have to scan the object twice and create - // an itermediate keys array. - if (priorKey !== undefined) { - execIteration(priorKey, i - 1); - } - priorKey = key; - i++; - }); - if (priorKey !== undefined) { - execIteration(priorKey, i - 1, true); - } - })(); - } - } - - if (i === 0) { - ret = inverse(this); - } - - return ret; - }); - }; - - module.exports = exports['default']; - /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) - -/***/ }), -/* 13 */ -/***/ (function(module, exports, __webpack_require__) { - - module.exports = { "default": __webpack_require__(14), __esModule: true }; - -/***/ }), -/* 14 */ -/***/ (function(module, exports, __webpack_require__) { - - __webpack_require__(15); - module.exports = __webpack_require__(21).Object.keys; - -/***/ }), -/* 15 */ -/***/ (function(module, exports, __webpack_require__) { - - // 19.1.2.14 Object.keys(O) - var toObject = __webpack_require__(16); - - __webpack_require__(18)('keys', function($keys){ - return function keys(it){ - return $keys(toObject(it)); - }; - }); - -/***/ }), -/* 16 */ -/***/ (function(module, exports, __webpack_require__) { - - // 7.1.13 ToObject(argument) - var defined = __webpack_require__(17); - module.exports = function(it){ - return Object(defined(it)); - }; - -/***/ }), -/* 17 */ -/***/ (function(module, exports) { - - // 7.2.1 RequireObjectCoercible(argument) - module.exports = function(it){ - if(it == undefined)throw TypeError("Can't call method on " + it); - return it; - }; - -/***/ }), -/* 18 */ -/***/ (function(module, exports, __webpack_require__) { - - // most Object methods by ES6 should accept primitives - var $export = __webpack_require__(19) - , core = __webpack_require__(21) - , fails = __webpack_require__(24); - module.exports = function(KEY, exec){ - var fn = (core.Object || {})[KEY] || Object[KEY] - , exp = {}; - exp[KEY] = exec(fn); - $export($export.S + $export.F * fails(function(){ fn(1); }), 'Object', exp); - }; - -/***/ }), -/* 19 */ -/***/ (function(module, exports, __webpack_require__) { - - var global = __webpack_require__(20) - , core = __webpack_require__(21) - , ctx = __webpack_require__(22) - , PROTOTYPE = 'prototype'; - - var $export = function(type, name, source){ - var IS_FORCED = type & $export.F - , IS_GLOBAL = type & $export.G - , IS_STATIC = type & $export.S - , IS_PROTO = type & $export.P - , IS_BIND = type & $export.B - , IS_WRAP = type & $export.W - , exports = IS_GLOBAL ? core : core[name] || (core[name] = {}) - , target = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE] - , key, own, out; - if(IS_GLOBAL)source = name; - for(key in source){ - // contains in native - own = !IS_FORCED && target && key in target; - if(own && key in exports)continue; - // export native or passed - out = own ? target[key] : source[key]; - // prevent global pollution for namespaces - exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key] - // bind timers to global for call from export context - : IS_BIND && own ? ctx(out, global) - // wrap global constructors for prevent change them in library - : IS_WRAP && target[key] == out ? (function(C){ - var F = function(param){ - return this instanceof C ? new C(param) : C(param); - }; - F[PROTOTYPE] = C[PROTOTYPE]; - return F; - // make static versions for prototype methods - })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out; - if(IS_PROTO)(exports[PROTOTYPE] || (exports[PROTOTYPE] = {}))[key] = out; - } - }; - // type bitmap - $export.F = 1; // forced - $export.G = 2; // global - $export.S = 4; // static - $export.P = 8; // proto - $export.B = 16; // bind - $export.W = 32; // wrap - module.exports = $export; - -/***/ }), -/* 20 */ -/***/ (function(module, exports) { - - // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 - var global = module.exports = typeof window != 'undefined' && window.Math == Math - ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')(); - if(typeof __g == 'number')__g = global; // eslint-disable-line no-undef - -/***/ }), -/* 21 */ -/***/ (function(module, exports) { - - var core = module.exports = {version: '1.2.6'}; - if(typeof __e == 'number')__e = core; // eslint-disable-line no-undef - -/***/ }), -/* 22 */ -/***/ (function(module, exports, __webpack_require__) { - - // optional / simple context binding - var aFunction = __webpack_require__(23); - module.exports = function(fn, that, length){ - aFunction(fn); - if(that === undefined)return fn; - switch(length){ - case 1: return function(a){ - return fn.call(that, a); - }; - case 2: return function(a, b){ - return fn.call(that, a, b); - }; - case 3: return function(a, b, c){ - return fn.call(that, a, b, c); - }; - } - return function(/* ...args */){ - return fn.apply(that, arguments); - }; - }; - -/***/ }), -/* 23 */ -/***/ (function(module, exports) { - - module.exports = function(it){ - if(typeof it != 'function')throw TypeError(it + ' is not a function!'); - return it; - }; - -/***/ }), -/* 24 */ -/***/ (function(module, exports) { - - module.exports = function(exec){ - try { - return !!exec(); - } catch(e){ - return true; - } - }; - -/***/ }), -/* 25 */ -/***/ (function(module, exports, __webpack_require__) { - - 'use strict'; - - var _interopRequireDefault = __webpack_require__(1)['default']; - - exports.__esModule = true; - - var _exception = __webpack_require__(6); - - var _exception2 = _interopRequireDefault(_exception); - - exports['default'] = function (instance) { - instance.registerHelper('helperMissing', function () /* [args, ]options */{ - if (arguments.length === 1) { - // A missing field in a {{foo}} construct. - return undefined; - } else { - // Someone is actually trying to call something, blow up. - throw new _exception2['default']('Missing helper: "' + arguments[arguments.length - 1].name + '"'); - } - }); - }; - - module.exports = exports['default']; - -/***/ }), -/* 26 */ -/***/ (function(module, exports, __webpack_require__) { - - 'use strict'; - - var _interopRequireDefault = __webpack_require__(1)['default']; - - exports.__esModule = true; - - var _utils = __webpack_require__(5); - - var _exception = __webpack_require__(6); - - var _exception2 = _interopRequireDefault(_exception); - - exports['default'] = function (instance) { - instance.registerHelper('if', function (conditional, options) { - if (arguments.length != 2) { - throw new _exception2['default']('#if requires exactly one argument'); - } - if (_utils.isFunction(conditional)) { - conditional = conditional.call(this); - } - - // Default behavior is to render the positive path if the value is truthy and not empty. - // The `includeZero` option may be set to treat the condtional as purely not empty based on the - // behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative. - if (!options.hash.includeZero && !conditional || _utils.isEmpty(conditional)) { - return options.inverse(this); - } else { - return options.fn(this); - } - }); - - instance.registerHelper('unless', function (conditional, options) { - if (arguments.length != 2) { - throw new _exception2['default']('#unless requires exactly one argument'); - } - return instance.helpers['if'].call(this, conditional, { - fn: options.inverse, - inverse: options.fn, - hash: options.hash - }); - }); - }; - - module.exports = exports['default']; - -/***/ }), -/* 27 */ -/***/ (function(module, exports) { - - 'use strict'; - - exports.__esModule = true; - - exports['default'] = function (instance) { - instance.registerHelper('log', function () /* message, options */{ - var args = [undefined], - options = arguments[arguments.length - 1]; - for (var i = 0; i < arguments.length - 1; i++) { - args.push(arguments[i]); - } - - var level = 1; - if (options.hash.level != null) { - level = options.hash.level; - } else if (options.data && options.data.level != null) { - level = options.data.level; - } - args[0] = level; - - instance.log.apply(instance, args); - }); - }; - - module.exports = exports['default']; - -/***/ }), -/* 28 */ -/***/ (function(module, exports) { - - 'use strict'; - - exports.__esModule = true; - - exports['default'] = function (instance) { - instance.registerHelper('lookup', function (obj, field, options) { - if (!obj) { - // Note for 5.0: Change to "obj == null" in 5.0 - return obj; - } - return options.lookupProperty(obj, field); - }); - }; - - module.exports = exports['default']; - -/***/ }), -/* 29 */ -/***/ (function(module, exports, __webpack_require__) { - - 'use strict'; - - var _interopRequireDefault = __webpack_require__(1)['default']; - - exports.__esModule = true; - - var _utils = __webpack_require__(5); - - var _exception = __webpack_require__(6); - - var _exception2 = _interopRequireDefault(_exception); - - exports['default'] = function (instance) { - instance.registerHelper('with', function (context, options) { - if (arguments.length != 2) { - throw new _exception2['default']('#with requires exactly one argument'); - } - if (_utils.isFunction(context)) { - context = context.call(this); - } - - var fn = options.fn; - - if (!_utils.isEmpty(context)) { - var data = options.data; - if (options.data && options.ids) { - data = _utils.createFrame(options.data); - data.contextPath = _utils.appendContextPath(options.data.contextPath, options.ids[0]); - } - - return fn(context, { - data: data, - blockParams: _utils.blockParams([context], [data && data.contextPath]) - }); - } else { - return options.inverse(this); - } - }); - }; - - module.exports = exports['default']; - -/***/ }), -/* 30 */ -/***/ (function(module, exports, __webpack_require__) { - - 'use strict'; - - var _interopRequireDefault = __webpack_require__(1)['default']; - - exports.__esModule = true; - exports.registerDefaultDecorators = registerDefaultDecorators; - - var _decoratorsInline = __webpack_require__(31); - - var _decoratorsInline2 = _interopRequireDefault(_decoratorsInline); - - function registerDefaultDecorators(instance) { - _decoratorsInline2['default'](instance); - } - -/***/ }), -/* 31 */ -/***/ (function(module, exports, __webpack_require__) { - - 'use strict'; - - exports.__esModule = true; - - var _utils = __webpack_require__(5); - - exports['default'] = function (instance) { - instance.registerDecorator('inline', function (fn, props, container, options) { - var ret = fn; - if (!props.partials) { - props.partials = {}; - ret = function (context, options) { - // Create a new partials stack frame prior to exec. - var original = container.partials; - container.partials = _utils.extend({}, original, props.partials); - var ret = fn(context, options); - container.partials = original; - return ret; - }; - } - - props.partials[options.args[0]] = options.fn; - - return ret; - }); - }; - - module.exports = exports['default']; - -/***/ }), -/* 32 */ -/***/ (function(module, exports, __webpack_require__) { - - 'use strict'; - - exports.__esModule = true; - - var _utils = __webpack_require__(5); - - var logger = { - methodMap: ['debug', 'info', 'warn', 'error'], - level: 'info', - - // Maps a given level value to the `methodMap` indexes above. - lookupLevel: function lookupLevel(level) { - if (typeof level === 'string') { - var levelMap = _utils.indexOf(logger.methodMap, level.toLowerCase()); - if (levelMap >= 0) { - level = levelMap; - } else { - level = parseInt(level, 10); - } - } - - return level; - }, - - // Can be overridden in the host environment - log: function log(level) { - level = logger.lookupLevel(level); - - if (typeof console !== 'undefined' && logger.lookupLevel(logger.level) <= level) { - var method = logger.methodMap[level]; - // eslint-disable-next-line no-console - if (!console[method]) { - method = 'log'; - } - - for (var _len = arguments.length, message = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - message[_key - 1] = arguments[_key]; - } - - console[method].apply(console, message); // eslint-disable-line no-console - } - } - }; - - exports['default'] = logger; - module.exports = exports['default']; - -/***/ }), -/* 33 */ -/***/ (function(module, exports, __webpack_require__) { - - 'use strict'; - - var _Object$create = __webpack_require__(34)['default']; - - var _Object$keys = __webpack_require__(13)['default']; - - var _interopRequireWildcard = __webpack_require__(3)['default']; - - exports.__esModule = true; - exports.createProtoAccessControl = createProtoAccessControl; - exports.resultIsAllowed = resultIsAllowed; - exports.resetLoggedProperties = resetLoggedProperties; - - var _createNewLookupObject = __webpack_require__(36); - - var _logger = __webpack_require__(32); - - var logger = _interopRequireWildcard(_logger); - - var loggedProperties = _Object$create(null); - - function createProtoAccessControl(runtimeOptions) { - var defaultMethodWhiteList = _Object$create(null); - defaultMethodWhiteList['constructor'] = false; - defaultMethodWhiteList['__defineGetter__'] = false; - defaultMethodWhiteList['__defineSetter__'] = false; - defaultMethodWhiteList['__lookupGetter__'] = false; - - var defaultPropertyWhiteList = _Object$create(null); - // eslint-disable-next-line no-proto - defaultPropertyWhiteList['__proto__'] = false; - - return { - properties: { - whitelist: _createNewLookupObject.createNewLookupObject(defaultPropertyWhiteList, runtimeOptions.allowedProtoProperties), - defaultValue: runtimeOptions.allowProtoPropertiesByDefault - }, - methods: { - whitelist: _createNewLookupObject.createNewLookupObject(defaultMethodWhiteList, runtimeOptions.allowedProtoMethods), - defaultValue: runtimeOptions.allowProtoMethodsByDefault - } - }; - } - - function resultIsAllowed(result, protoAccessControl, propertyName) { - if (typeof result === 'function') { - return checkWhiteList(protoAccessControl.methods, propertyName); - } else { - return checkWhiteList(protoAccessControl.properties, propertyName); - } - } - - function checkWhiteList(protoAccessControlForType, propertyName) { - if (protoAccessControlForType.whitelist[propertyName] !== undefined) { - return protoAccessControlForType.whitelist[propertyName] === true; - } - if (protoAccessControlForType.defaultValue !== undefined) { - return protoAccessControlForType.defaultValue; - } - logUnexpecedPropertyAccessOnce(propertyName); - return false; - } - - function logUnexpecedPropertyAccessOnce(propertyName) { - if (loggedProperties[propertyName] !== true) { - loggedProperties[propertyName] = true; - logger.log('error', 'Handlebars: Access has been denied to resolve the property "' + propertyName + '" because it is not an "own property" of its parent.\n' + 'You can add a runtime option to disable the check or this warning:\n' + 'See https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access for details'); - } - } - - function resetLoggedProperties() { - _Object$keys(loggedProperties).forEach(function (propertyName) { - delete loggedProperties[propertyName]; - }); - } - -/***/ }), -/* 34 */ -/***/ (function(module, exports, __webpack_require__) { - - module.exports = { "default": __webpack_require__(35), __esModule: true }; - -/***/ }), -/* 35 */ -/***/ (function(module, exports, __webpack_require__) { - - var $ = __webpack_require__(9); - module.exports = function create(P, D){ - return $.create(P, D); - }; - -/***/ }), -/* 36 */ -/***/ (function(module, exports, __webpack_require__) { - - 'use strict'; - - var _Object$create = __webpack_require__(34)['default']; - - exports.__esModule = true; - exports.createNewLookupObject = createNewLookupObject; - - var _utils = __webpack_require__(5); - - /** - * Create a new object with "null"-prototype to avoid truthy results on prototype properties. - * The resulting object can be used with "object[property]" to check if a property exists - * @param {...object} sources a varargs parameter of source objects that will be merged - * @returns {object} - */ - - function createNewLookupObject() { - for (var _len = arguments.length, sources = Array(_len), _key = 0; _key < _len; _key++) { - sources[_key] = arguments[_key]; - } - - return _utils.extend.apply(undefined, [_Object$create(null)].concat(sources)); - } - -/***/ }), -/* 37 */ -/***/ (function(module, exports) { - - // Build out our basic SafeString type - 'use strict'; - - exports.__esModule = true; - function SafeString(string) { - this.string = string; - } - - SafeString.prototype.toString = SafeString.prototype.toHTML = function () { - return '' + this.string; - }; - - exports['default'] = SafeString; - module.exports = exports['default']; - -/***/ }), -/* 38 */ -/***/ (function(module, exports, __webpack_require__) { - - 'use strict'; - - var _Object$seal = __webpack_require__(39)['default']; - - var _Object$keys = __webpack_require__(13)['default']; - - var _interopRequireWildcard = __webpack_require__(3)['default']; - - var _interopRequireDefault = __webpack_require__(1)['default']; - - exports.__esModule = true; - exports.checkRevision = checkRevision; - exports.template = template; - exports.wrapProgram = wrapProgram; - exports.resolvePartial = resolvePartial; - exports.invokePartial = invokePartial; - exports.noop = noop; - - var _utils = __webpack_require__(5); - - var Utils = _interopRequireWildcard(_utils); - - var _exception = __webpack_require__(6); - - var _exception2 = _interopRequireDefault(_exception); - - var _base = __webpack_require__(4); - - var _helpers = __webpack_require__(10); - - var _internalWrapHelper = __webpack_require__(43); - - var _internalProtoAccess = __webpack_require__(33); - - function checkRevision(compilerInfo) { - var compilerRevision = compilerInfo && compilerInfo[0] || 1, - currentRevision = _base.COMPILER_REVISION; - - if (compilerRevision >= _base.LAST_COMPATIBLE_COMPILER_REVISION && compilerRevision <= _base.COMPILER_REVISION) { - return; - } - - if (compilerRevision < _base.LAST_COMPATIBLE_COMPILER_REVISION) { - var runtimeVersions = _base.REVISION_CHANGES[currentRevision], - compilerVersions = _base.REVISION_CHANGES[compilerRevision]; - throw new _exception2['default']('Template was precompiled with an older version of Handlebars than the current runtime. ' + 'Please update your precompiler to a newer version (' + runtimeVersions + ') or downgrade your runtime to an older version (' + compilerVersions + ').'); - } else { - // Use the embedded version info since the runtime doesn't know about this revision yet - throw new _exception2['default']('Template was precompiled with a newer version of Handlebars than the current runtime. ' + 'Please update your runtime to a newer version (' + compilerInfo[1] + ').'); - } - } - - function template(templateSpec, env) { - /* istanbul ignore next */ - if (!env) { - throw new _exception2['default']('No environment passed to template'); - } - if (!templateSpec || !templateSpec.main) { - throw new _exception2['default']('Unknown template object: ' + typeof templateSpec); - } - - templateSpec.main.decorator = templateSpec.main_d; - - // Note: Using env.VM references rather than local var references throughout this section to allow - // for external users to override these as pseudo-supported APIs. - env.VM.checkRevision(templateSpec.compiler); - - // backwards compatibility for precompiled templates with compiler-version 7 (<4.3.0) - var templateWasPrecompiledWithCompilerV7 = templateSpec.compiler && templateSpec.compiler[0] === 7; - - function invokePartialWrapper(partial, context, options) { - if (options.hash) { - context = Utils.extend({}, context, options.hash); - if (options.ids) { - options.ids[0] = true; - } - } - partial = env.VM.resolvePartial.call(this, partial, context, options); - - var extendedOptions = Utils.extend({}, options, { - hooks: this.hooks, - protoAccessControl: this.protoAccessControl - }); - - var result = env.VM.invokePartial.call(this, partial, context, extendedOptions); - - if (result == null && env.compile) { - options.partials[options.name] = env.compile(partial, templateSpec.compilerOptions, env); - result = options.partials[options.name](context, extendedOptions); - } - if (result != null) { - if (options.indent) { - var lines = result.split('\n'); - for (var i = 0, l = lines.length; i < l; i++) { - if (!lines[i] && i + 1 === l) { - break; - } - - lines[i] = options.indent + lines[i]; - } - result = lines.join('\n'); - } - return result; - } else { - throw new _exception2['default']('The partial ' + options.name + ' could not be compiled when running in runtime-only mode'); - } - } - - // Just add water - var container = { - strict: function strict(obj, name, loc) { - if (!obj || !(name in obj)) { - throw new _exception2['default']('"' + name + '" not defined in ' + obj, { - loc: loc - }); - } - return obj[name]; - }, - lookupProperty: function lookupProperty(parent, propertyName) { - var result = parent[propertyName]; - if (result == null) { - return result; - } - if (Object.prototype.hasOwnProperty.call(parent, propertyName)) { - return result; - } - - if (_internalProtoAccess.resultIsAllowed(result, container.protoAccessControl, propertyName)) { - return result; - } - return undefined; - }, - lookup: function lookup(depths, name) { - var len = depths.length; - for (var i = 0; i < len; i++) { - var result = depths[i] && container.lookupProperty(depths[i], name); - if (result != null) { - return depths[i][name]; - } - } - }, - lambda: function lambda(current, context) { - return typeof current === 'function' ? current.call(context) : current; - }, - - escapeExpression: Utils.escapeExpression, - invokePartial: invokePartialWrapper, - - fn: function fn(i) { - var ret = templateSpec[i]; - ret.decorator = templateSpec[i + '_d']; - return ret; - }, - - programs: [], - program: function program(i, data, declaredBlockParams, blockParams, depths) { - var programWrapper = this.programs[i], - fn = this.fn(i); - if (data || depths || blockParams || declaredBlockParams) { - programWrapper = wrapProgram(this, i, fn, data, declaredBlockParams, blockParams, depths); - } else if (!programWrapper) { - programWrapper = this.programs[i] = wrapProgram(this, i, fn); - } - return programWrapper; - }, - - data: function data(value, depth) { - while (value && depth--) { - value = value._parent; - } - return value; - }, - mergeIfNeeded: function mergeIfNeeded(param, common) { - var obj = param || common; - - if (param && common && param !== common) { - obj = Utils.extend({}, common, param); - } - - return obj; - }, - // An empty object to use as replacement for null-contexts - nullContext: _Object$seal({}), - - noop: env.VM.noop, - compilerInfo: templateSpec.compiler - }; - - function ret(context) { - var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; - - var data = options.data; - - ret._setup(options); - if (!options.partial && templateSpec.useData) { - data = initData(context, data); - } - var depths = undefined, - blockParams = templateSpec.useBlockParams ? [] : undefined; - if (templateSpec.useDepths) { - if (options.depths) { - depths = context != options.depths[0] ? [context].concat(options.depths) : options.depths; - } else { - depths = [context]; - } - } - - function main(context /*, options*/) { - return '' + templateSpec.main(container, context, container.helpers, container.partials, data, blockParams, depths); - } - - main = executeDecorators(templateSpec.main, main, container, options.depths || [], data, blockParams); - return main(context, options); - } - - ret.isTop = true; - - ret._setup = function (options) { - if (!options.partial) { - var mergedHelpers = Utils.extend({}, env.helpers, options.helpers); - wrapHelpersToPassLookupProperty(mergedHelpers, container); - container.helpers = mergedHelpers; - - if (templateSpec.usePartial) { - // Use mergeIfNeeded here to prevent compiling global partials multiple times - container.partials = container.mergeIfNeeded(options.partials, env.partials); - } - if (templateSpec.usePartial || templateSpec.useDecorators) { - container.decorators = Utils.extend({}, env.decorators, options.decorators); - } - - container.hooks = {}; - container.protoAccessControl = _internalProtoAccess.createProtoAccessControl(options); - - var keepHelperInHelpers = options.allowCallsToHelperMissing || templateWasPrecompiledWithCompilerV7; - _helpers.moveHelperToHooks(container, 'helperMissing', keepHelperInHelpers); - _helpers.moveHelperToHooks(container, 'blockHelperMissing', keepHelperInHelpers); - } else { - container.protoAccessControl = options.protoAccessControl; // internal option - container.helpers = options.helpers; - container.partials = options.partials; - container.decorators = options.decorators; - container.hooks = options.hooks; - } - }; - - ret._child = function (i, data, blockParams, depths) { - if (templateSpec.useBlockParams && !blockParams) { - throw new _exception2['default']('must pass block params'); - } - if (templateSpec.useDepths && !depths) { - throw new _exception2['default']('must pass parent depths'); - } - - return wrapProgram(container, i, templateSpec[i], data, 0, blockParams, depths); - }; - return ret; - } - - function wrapProgram(container, i, fn, data, declaredBlockParams, blockParams, depths) { - function prog(context) { - var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; - - var currentDepths = depths; - if (depths && context != depths[0] && !(context === container.nullContext && depths[0] === null)) { - currentDepths = [context].concat(depths); - } - - return fn(container, context, container.helpers, container.partials, options.data || data, blockParams && [options.blockParams].concat(blockParams), currentDepths); - } - - prog = executeDecorators(fn, prog, container, depths, data, blockParams); - - prog.program = i; - prog.depth = depths ? depths.length : 0; - prog.blockParams = declaredBlockParams || 0; - return prog; - } - - /** - * This is currently part of the official API, therefore implementation details should not be changed. - */ - - function resolvePartial(partial, context, options) { - if (!partial) { - if (options.name === '@partial-block') { - partial = options.data['partial-block']; - } else { - partial = options.partials[options.name]; - } - } else if (!partial.call && !options.name) { - // This is a dynamic partial that returned a string - options.name = partial; - partial = options.partials[partial]; - } - return partial; - } - - function invokePartial(partial, context, options) { - // Use the current closure context to save the partial-block if this partial - var currentPartialBlock = options.data && options.data['partial-block']; - options.partial = true; - if (options.ids) { - options.data.contextPath = options.ids[0] || options.data.contextPath; - } - - var partialBlock = undefined; - if (options.fn && options.fn !== noop) { - (function () { - options.data = _base.createFrame(options.data); - // Wrapper function to get access to currentPartialBlock from the closure - var fn = options.fn; - partialBlock = options.data['partial-block'] = function partialBlockWrapper(context) { - var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; - - // Restore the partial-block from the closure for the execution of the block - // i.e. the part inside the block of the partial call. - options.data = _base.createFrame(options.data); - options.data['partial-block'] = currentPartialBlock; - return fn(context, options); - }; - if (fn.partials) { - options.partials = Utils.extend({}, options.partials, fn.partials); - } - })(); - } - - if (partial === undefined && partialBlock) { - partial = partialBlock; - } - - if (partial === undefined) { - throw new _exception2['default']('The partial ' + options.name + ' could not be found'); - } else if (partial instanceof Function) { - return partial(context, options); - } - } - - function noop() { - return ''; - } - - function initData(context, data) { - if (!data || !('root' in data)) { - data = data ? _base.createFrame(data) : {}; - data.root = context; - } - return data; - } - - function executeDecorators(fn, prog, container, depths, data, blockParams) { - if (fn.decorator) { - var props = {}; - prog = fn.decorator(prog, props, container, depths && depths[0], data, blockParams, depths); - Utils.extend(prog, props); - } - return prog; - } - - function wrapHelpersToPassLookupProperty(mergedHelpers, container) { - _Object$keys(mergedHelpers).forEach(function (helperName) { - var helper = mergedHelpers[helperName]; - mergedHelpers[helperName] = passLookupPropertyOption(helper, container); - }); - } - - function passLookupPropertyOption(helper, container) { - var lookupProperty = container.lookupProperty; - return _internalWrapHelper.wrapHelper(helper, function (options) { - return Utils.extend({ lookupProperty: lookupProperty }, options); - }); - } - -/***/ }), -/* 39 */ -/***/ (function(module, exports, __webpack_require__) { - - module.exports = { "default": __webpack_require__(40), __esModule: true }; - -/***/ }), -/* 40 */ -/***/ (function(module, exports, __webpack_require__) { - - __webpack_require__(41); - module.exports = __webpack_require__(21).Object.seal; - -/***/ }), -/* 41 */ -/***/ (function(module, exports, __webpack_require__) { - - // 19.1.2.17 Object.seal(O) - var isObject = __webpack_require__(42); - - __webpack_require__(18)('seal', function($seal){ - return function seal(it){ - return $seal && isObject(it) ? $seal(it) : it; - }; - }); - -/***/ }), -/* 42 */ -/***/ (function(module, exports) { - - module.exports = function(it){ - return typeof it === 'object' ? it !== null : typeof it === 'function'; - }; - -/***/ }), -/* 43 */ -/***/ (function(module, exports) { - - 'use strict'; - - exports.__esModule = true; - exports.wrapHelper = wrapHelper; - - function wrapHelper(helper, transformOptionsFn) { - if (typeof helper !== 'function') { - // This should not happen, but apparently it does in https://github.com/wycats/handlebars.js/issues/1639 - // We try to make the wrapper least-invasive by not wrapping it, if the helper is not a function. - return helper; - } - var wrapper = function wrapper() /* dynamic arguments */{ - var options = arguments[arguments.length - 1]; - arguments[arguments.length - 1] = transformOptionsFn(options); - return helper.apply(this, arguments); - }; - return wrapper; - } - -/***/ }), -/* 44 */ -/***/ (function(module, exports) { - - /* WEBPACK VAR INJECTION */(function(global) {'use strict'; - - exports.__esModule = true; - - exports['default'] = function (Handlebars) { - /* istanbul ignore next */ - var root = typeof global !== 'undefined' ? global : window, - $Handlebars = root.Handlebars; - /* istanbul ignore next */ - Handlebars.noConflict = function () { - if (root.Handlebars === Handlebars) { - root.Handlebars = $Handlebars; - } - return Handlebars; - }; - }; - - module.exports = exports['default']; - /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()))) - -/***/ }), -/* 45 */ -/***/ (function(module, exports) { - - 'use strict'; - - exports.__esModule = true; - var AST = { - // Public API used to evaluate derived attributes regarding AST nodes - helpers: { - // a mustache is definitely a helper if: - // * it is an eligible helper, and - // * it has at least one parameter or hash segment - helperExpression: function helperExpression(node) { - return node.type === 'SubExpression' || (node.type === 'MustacheStatement' || node.type === 'BlockStatement') && !!(node.params && node.params.length || node.hash); - }, - - scopedId: function scopedId(path) { - return (/^\.|this\b/.test(path.original) - ); - }, - - // an ID is simple if it only has one part, and that part is not - // `..` or `this`. - simpleId: function simpleId(path) { - return path.parts.length === 1 && !AST.helpers.scopedId(path) && !path.depth; - } - } - }; - - // Must be exported as an object rather than the root of the module as the jison lexer - // must modify the object to operate properly. - exports['default'] = AST; - module.exports = exports['default']; - -/***/ }), -/* 46 */ -/***/ (function(module, exports, __webpack_require__) { - - 'use strict'; - - var _interopRequireDefault = __webpack_require__(1)['default']; - - var _interopRequireWildcard = __webpack_require__(3)['default']; - - exports.__esModule = true; - exports.parseWithoutProcessing = parseWithoutProcessing; - exports.parse = parse; - - var _parser = __webpack_require__(47); - - var _parser2 = _interopRequireDefault(_parser); - - var _whitespaceControl = __webpack_require__(48); - - var _whitespaceControl2 = _interopRequireDefault(_whitespaceControl); - - var _helpers = __webpack_require__(50); - - var Helpers = _interopRequireWildcard(_helpers); - - var _utils = __webpack_require__(5); - - exports.parser = _parser2['default']; - - var yy = {}; - _utils.extend(yy, Helpers); - - function parseWithoutProcessing(input, options) { - // Just return if an already-compiled AST was passed in. - if (input.type === 'Program') { - return input; - } - - _parser2['default'].yy = yy; - - // Altering the shared object here, but this is ok as parser is a sync operation - yy.locInfo = function (locInfo) { - return new yy.SourceLocation(options && options.srcName, locInfo); - }; - - var ast = _parser2['default'].parse(input); - - return ast; - } - - function parse(input, options) { - var ast = parseWithoutProcessing(input, options); - var strip = new _whitespaceControl2['default'](options); - - return strip.accept(ast); - } - -/***/ }), -/* 47 */ -/***/ (function(module, exports) { - - // File ignored in coverage tests via setting in .istanbul.yml - /* Jison generated parser */ - "use strict"; - - exports.__esModule = true; - var handlebars = (function () { - var parser = { trace: function trace() {}, - yy: {}, - symbols_: { "error": 2, "root": 3, "program": 4, "EOF": 5, "program_repetition0": 6, "statement": 7, "mustache": 8, "block": 9, "rawBlock": 10, "partial": 11, "partialBlock": 12, "content": 13, "COMMENT": 14, "CONTENT": 15, "openRawBlock": 16, "rawBlock_repetition0": 17, "END_RAW_BLOCK": 18, "OPEN_RAW_BLOCK": 19, "helperName": 20, "openRawBlock_repetition0": 21, "openRawBlock_option0": 22, "CLOSE_RAW_BLOCK": 23, "openBlock": 24, "block_option0": 25, "closeBlock": 26, "openInverse": 27, "block_option1": 28, "OPEN_BLOCK": 29, "openBlock_repetition0": 30, "openBlock_option0": 31, "openBlock_option1": 32, "CLOSE": 33, "OPEN_INVERSE": 34, "openInverse_repetition0": 35, "openInverse_option0": 36, "openInverse_option1": 37, "openInverseChain": 38, "OPEN_INVERSE_CHAIN": 39, "openInverseChain_repetition0": 40, "openInverseChain_option0": 41, "openInverseChain_option1": 42, "inverseAndProgram": 43, "INVERSE": 44, "inverseChain": 45, "inverseChain_option0": 46, "OPEN_ENDBLOCK": 47, "OPEN": 48, "mustache_repetition0": 49, "mustache_option0": 50, "OPEN_UNESCAPED": 51, "mustache_repetition1": 52, "mustache_option1": 53, "CLOSE_UNESCAPED": 54, "OPEN_PARTIAL": 55, "partialName": 56, "partial_repetition0": 57, "partial_option0": 58, "openPartialBlock": 59, "OPEN_PARTIAL_BLOCK": 60, "openPartialBlock_repetition0": 61, "openPartialBlock_option0": 62, "param": 63, "sexpr": 64, "OPEN_SEXPR": 65, "sexpr_repetition0": 66, "sexpr_option0": 67, "CLOSE_SEXPR": 68, "hash": 69, "hash_repetition_plus0": 70, "hashSegment": 71, "ID": 72, "EQUALS": 73, "blockParams": 74, "OPEN_BLOCK_PARAMS": 75, "blockParams_repetition_plus0": 76, "CLOSE_BLOCK_PARAMS": 77, "path": 78, "dataName": 79, "STRING": 80, "NUMBER": 81, "BOOLEAN": 82, "UNDEFINED": 83, "NULL": 84, "DATA": 85, "pathSegments": 86, "SEP": 87, "$accept": 0, "$end": 1 }, - terminals_: { 2: "error", 5: "EOF", 14: "COMMENT", 15: "CONTENT", 18: "END_RAW_BLOCK", 19: "OPEN_RAW_BLOCK", 23: "CLOSE_RAW_BLOCK", 29: "OPEN_BLOCK", 33: "CLOSE", 34: "OPEN_INVERSE", 39: "OPEN_INVERSE_CHAIN", 44: "INVERSE", 47: "OPEN_ENDBLOCK", 48: "OPEN", 51: "OPEN_UNESCAPED", 54: "CLOSE_UNESCAPED", 55: "OPEN_PARTIAL", 60: "OPEN_PARTIAL_BLOCK", 65: "OPEN_SEXPR", 68: "CLOSE_SEXPR", 72: "ID", 73: "EQUALS", 75: "OPEN_BLOCK_PARAMS", 77: "CLOSE_BLOCK_PARAMS", 80: "STRING", 81: "NUMBER", 82: "BOOLEAN", 83: "UNDEFINED", 84: "NULL", 85: "DATA", 87: "SEP" }, - productions_: [0, [3, 2], [4, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [7, 1], [13, 1], [10, 3], [16, 5], [9, 4], [9, 4], [24, 6], [27, 6], [38, 6], [43, 2], [45, 3], [45, 1], [26, 3], [8, 5], [8, 5], [11, 5], [12, 3], [59, 5], [63, 1], [63, 1], [64, 5], [69, 1], [71, 3], [74, 3], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [20, 1], [56, 1], [56, 1], [79, 2], [78, 1], [86, 3], [86, 1], [6, 0], [6, 2], [17, 0], [17, 2], [21, 0], [21, 2], [22, 0], [22, 1], [25, 0], [25, 1], [28, 0], [28, 1], [30, 0], [30, 2], [31, 0], [31, 1], [32, 0], [32, 1], [35, 0], [35, 2], [36, 0], [36, 1], [37, 0], [37, 1], [40, 0], [40, 2], [41, 0], [41, 1], [42, 0], [42, 1], [46, 0], [46, 1], [49, 0], [49, 2], [50, 0], [50, 1], [52, 0], [52, 2], [53, 0], [53, 1], [57, 0], [57, 2], [58, 0], [58, 1], [61, 0], [61, 2], [62, 0], [62, 1], [66, 0], [66, 2], [67, 0], [67, 1], [70, 1], [70, 2], [76, 1], [76, 2]], - performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$) { - - var $0 = $$.length - 1; - switch (yystate) { - case 1: - return $$[$0 - 1]; - break; - case 2: - this.$ = yy.prepareProgram($$[$0]); - break; - case 3: - this.$ = $$[$0]; - break; - case 4: - this.$ = $$[$0]; - break; - case 5: - this.$ = $$[$0]; - break; - case 6: - this.$ = $$[$0]; - break; - case 7: - this.$ = $$[$0]; - break; - case 8: - this.$ = $$[$0]; - break; - case 9: - this.$ = { - type: 'CommentStatement', - value: yy.stripComment($$[$0]), - strip: yy.stripFlags($$[$0], $$[$0]), - loc: yy.locInfo(this._$) - }; - - break; - case 10: - this.$ = { - type: 'ContentStatement', - original: $$[$0], - value: $$[$0], - loc: yy.locInfo(this._$) - }; - - break; - case 11: - this.$ = yy.prepareRawBlock($$[$0 - 2], $$[$0 - 1], $$[$0], this._$); - break; - case 12: - this.$ = { path: $$[$0 - 3], params: $$[$0 - 2], hash: $$[$0 - 1] }; - break; - case 13: - this.$ = yy.prepareBlock($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0], false, this._$); - break; - case 14: - this.$ = yy.prepareBlock($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0], true, this._$); - break; - case 15: - this.$ = { open: $$[$0 - 5], path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) }; - break; - case 16: - this.$ = { path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) }; - break; - case 17: - this.$ = { path: $$[$0 - 4], params: $$[$0 - 3], hash: $$[$0 - 2], blockParams: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 5], $$[$0]) }; - break; - case 18: - this.$ = { strip: yy.stripFlags($$[$0 - 1], $$[$0 - 1]), program: $$[$0] }; - break; - case 19: - var inverse = yy.prepareBlock($$[$0 - 2], $$[$0 - 1], $$[$0], $$[$0], false, this._$), - program = yy.prepareProgram([inverse], $$[$0 - 1].loc); - program.chained = true; - - this.$ = { strip: $$[$0 - 2].strip, program: program, chain: true }; - - break; - case 20: - this.$ = $$[$0]; - break; - case 21: - this.$ = { path: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 2], $$[$0]) }; - break; - case 22: - this.$ = yy.prepareMustache($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0 - 4], yy.stripFlags($$[$0 - 4], $$[$0]), this._$); - break; - case 23: - this.$ = yy.prepareMustache($$[$0 - 3], $$[$0 - 2], $$[$0 - 1], $$[$0 - 4], yy.stripFlags($$[$0 - 4], $$[$0]), this._$); - break; - case 24: - this.$ = { - type: 'PartialStatement', - name: $$[$0 - 3], - params: $$[$0 - 2], - hash: $$[$0 - 1], - indent: '', - strip: yy.stripFlags($$[$0 - 4], $$[$0]), - loc: yy.locInfo(this._$) - }; - - break; - case 25: - this.$ = yy.preparePartialBlock($$[$0 - 2], $$[$0 - 1], $$[$0], this._$); - break; - case 26: - this.$ = { path: $$[$0 - 3], params: $$[$0 - 2], hash: $$[$0 - 1], strip: yy.stripFlags($$[$0 - 4], $$[$0]) }; - break; - case 27: - this.$ = $$[$0]; - break; - case 28: - this.$ = $$[$0]; - break; - case 29: - this.$ = { - type: 'SubExpression', - path: $$[$0 - 3], - params: $$[$0 - 2], - hash: $$[$0 - 1], - loc: yy.locInfo(this._$) - }; - - break; - case 30: - this.$ = { type: 'Hash', pairs: $$[$0], loc: yy.locInfo(this._$) }; - break; - case 31: - this.$ = { type: 'HashPair', key: yy.id($$[$0 - 2]), value: $$[$0], loc: yy.locInfo(this._$) }; - break; - case 32: - this.$ = yy.id($$[$0 - 1]); - break; - case 33: - this.$ = $$[$0]; - break; - case 34: - this.$ = $$[$0]; - break; - case 35: - this.$ = { type: 'StringLiteral', value: $$[$0], original: $$[$0], loc: yy.locInfo(this._$) }; - break; - case 36: - this.$ = { type: 'NumberLiteral', value: Number($$[$0]), original: Number($$[$0]), loc: yy.locInfo(this._$) }; - break; - case 37: - this.$ = { type: 'BooleanLiteral', value: $$[$0] === 'true', original: $$[$0] === 'true', loc: yy.locInfo(this._$) }; - break; - case 38: - this.$ = { type: 'UndefinedLiteral', original: undefined, value: undefined, loc: yy.locInfo(this._$) }; - break; - case 39: - this.$ = { type: 'NullLiteral', original: null, value: null, loc: yy.locInfo(this._$) }; - break; - case 40: - this.$ = $$[$0]; - break; - case 41: - this.$ = $$[$0]; - break; - case 42: - this.$ = yy.preparePath(true, $$[$0], this._$); - break; - case 43: - this.$ = yy.preparePath(false, $$[$0], this._$); - break; - case 44: - $$[$0 - 2].push({ part: yy.id($$[$0]), original: $$[$0], separator: $$[$0 - 1] });this.$ = $$[$0 - 2]; - break; - case 45: - this.$ = [{ part: yy.id($$[$0]), original: $$[$0] }]; - break; - case 46: - this.$ = []; - break; - case 47: - $$[$0 - 1].push($$[$0]); - break; - case 48: - this.$ = []; - break; - case 49: - $$[$0 - 1].push($$[$0]); - break; - case 50: - this.$ = []; - break; - case 51: - $$[$0 - 1].push($$[$0]); - break; - case 58: - this.$ = []; - break; - case 59: - $$[$0 - 1].push($$[$0]); - break; - case 64: - this.$ = []; - break; - case 65: - $$[$0 - 1].push($$[$0]); - break; - case 70: - this.$ = []; - break; - case 71: - $$[$0 - 1].push($$[$0]); - break; - case 78: - this.$ = []; - break; - case 79: - $$[$0 - 1].push($$[$0]); - break; - case 82: - this.$ = []; - break; - case 83: - $$[$0 - 1].push($$[$0]); - break; - case 86: - this.$ = []; - break; - case 87: - $$[$0 - 1].push($$[$0]); - break; - case 90: - this.$ = []; - break; - case 91: - $$[$0 - 1].push($$[$0]); - break; - case 94: - this.$ = []; - break; - case 95: - $$[$0 - 1].push($$[$0]); - break; - case 98: - this.$ = [$$[$0]]; - break; - case 99: - $$[$0 - 1].push($$[$0]); - break; - case 100: - this.$ = [$$[$0]]; - break; - case 101: - $$[$0 - 1].push($$[$0]); - break; - } - }, - table: [{ 3: 1, 4: 2, 5: [2, 46], 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 1: [3] }, { 5: [1, 4] }, { 5: [2, 2], 7: 5, 8: 6, 9: 7, 10: 8, 11: 9, 12: 10, 13: 11, 14: [1, 12], 15: [1, 20], 16: 17, 19: [1, 23], 24: 15, 27: 16, 29: [1, 21], 34: [1, 22], 39: [2, 2], 44: [2, 2], 47: [2, 2], 48: [1, 13], 51: [1, 14], 55: [1, 18], 59: 19, 60: [1, 24] }, { 1: [2, 1] }, { 5: [2, 47], 14: [2, 47], 15: [2, 47], 19: [2, 47], 29: [2, 47], 34: [2, 47], 39: [2, 47], 44: [2, 47], 47: [2, 47], 48: [2, 47], 51: [2, 47], 55: [2, 47], 60: [2, 47] }, { 5: [2, 3], 14: [2, 3], 15: [2, 3], 19: [2, 3], 29: [2, 3], 34: [2, 3], 39: [2, 3], 44: [2, 3], 47: [2, 3], 48: [2, 3], 51: [2, 3], 55: [2, 3], 60: [2, 3] }, { 5: [2, 4], 14: [2, 4], 15: [2, 4], 19: [2, 4], 29: [2, 4], 34: [2, 4], 39: [2, 4], 44: [2, 4], 47: [2, 4], 48: [2, 4], 51: [2, 4], 55: [2, 4], 60: [2, 4] }, { 5: [2, 5], 14: [2, 5], 15: [2, 5], 19: [2, 5], 29: [2, 5], 34: [2, 5], 39: [2, 5], 44: [2, 5], 47: [2, 5], 48: [2, 5], 51: [2, 5], 55: [2, 5], 60: [2, 5] }, { 5: [2, 6], 14: [2, 6], 15: [2, 6], 19: [2, 6], 29: [2, 6], 34: [2, 6], 39: [2, 6], 44: [2, 6], 47: [2, 6], 48: [2, 6], 51: [2, 6], 55: [2, 6], 60: [2, 6] }, { 5: [2, 7], 14: [2, 7], 15: [2, 7], 19: [2, 7], 29: [2, 7], 34: [2, 7], 39: [2, 7], 44: [2, 7], 47: [2, 7], 48: [2, 7], 51: [2, 7], 55: [2, 7], 60: [2, 7] }, { 5: [2, 8], 14: [2, 8], 15: [2, 8], 19: [2, 8], 29: [2, 8], 34: [2, 8], 39: [2, 8], 44: [2, 8], 47: [2, 8], 48: [2, 8], 51: [2, 8], 55: [2, 8], 60: [2, 8] }, { 5: [2, 9], 14: [2, 9], 15: [2, 9], 19: [2, 9], 29: [2, 9], 34: [2, 9], 39: [2, 9], 44: [2, 9], 47: [2, 9], 48: [2, 9], 51: [2, 9], 55: [2, 9], 60: [2, 9] }, { 20: 25, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 36, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 37, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 39: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 4: 38, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 15: [2, 48], 17: 39, 18: [2, 48] }, { 20: 41, 56: 40, 64: 42, 65: [1, 43], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 44, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 5: [2, 10], 14: [2, 10], 15: [2, 10], 18: [2, 10], 19: [2, 10], 29: [2, 10], 34: [2, 10], 39: [2, 10], 44: [2, 10], 47: [2, 10], 48: [2, 10], 51: [2, 10], 55: [2, 10], 60: [2, 10] }, { 20: 45, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 46, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 47, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 41, 56: 48, 64: 42, 65: [1, 43], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [2, 78], 49: 49, 65: [2, 78], 72: [2, 78], 80: [2, 78], 81: [2, 78], 82: [2, 78], 83: [2, 78], 84: [2, 78], 85: [2, 78] }, { 23: [2, 33], 33: [2, 33], 54: [2, 33], 65: [2, 33], 68: [2, 33], 72: [2, 33], 75: [2, 33], 80: [2, 33], 81: [2, 33], 82: [2, 33], 83: [2, 33], 84: [2, 33], 85: [2, 33] }, { 23: [2, 34], 33: [2, 34], 54: [2, 34], 65: [2, 34], 68: [2, 34], 72: [2, 34], 75: [2, 34], 80: [2, 34], 81: [2, 34], 82: [2, 34], 83: [2, 34], 84: [2, 34], 85: [2, 34] }, { 23: [2, 35], 33: [2, 35], 54: [2, 35], 65: [2, 35], 68: [2, 35], 72: [2, 35], 75: [2, 35], 80: [2, 35], 81: [2, 35], 82: [2, 35], 83: [2, 35], 84: [2, 35], 85: [2, 35] }, { 23: [2, 36], 33: [2, 36], 54: [2, 36], 65: [2, 36], 68: [2, 36], 72: [2, 36], 75: [2, 36], 80: [2, 36], 81: [2, 36], 82: [2, 36], 83: [2, 36], 84: [2, 36], 85: [2, 36] }, { 23: [2, 37], 33: [2, 37], 54: [2, 37], 65: [2, 37], 68: [2, 37], 72: [2, 37], 75: [2, 37], 80: [2, 37], 81: [2, 37], 82: [2, 37], 83: [2, 37], 84: [2, 37], 85: [2, 37] }, { 23: [2, 38], 33: [2, 38], 54: [2, 38], 65: [2, 38], 68: [2, 38], 72: [2, 38], 75: [2, 38], 80: [2, 38], 81: [2, 38], 82: [2, 38], 83: [2, 38], 84: [2, 38], 85: [2, 38] }, { 23: [2, 39], 33: [2, 39], 54: [2, 39], 65: [2, 39], 68: [2, 39], 72: [2, 39], 75: [2, 39], 80: [2, 39], 81: [2, 39], 82: [2, 39], 83: [2, 39], 84: [2, 39], 85: [2, 39] }, { 23: [2, 43], 33: [2, 43], 54: [2, 43], 65: [2, 43], 68: [2, 43], 72: [2, 43], 75: [2, 43], 80: [2, 43], 81: [2, 43], 82: [2, 43], 83: [2, 43], 84: [2, 43], 85: [2, 43], 87: [1, 50] }, { 72: [1, 35], 86: 51 }, { 23: [2, 45], 33: [2, 45], 54: [2, 45], 65: [2, 45], 68: [2, 45], 72: [2, 45], 75: [2, 45], 80: [2, 45], 81: [2, 45], 82: [2, 45], 83: [2, 45], 84: [2, 45], 85: [2, 45], 87: [2, 45] }, { 52: 52, 54: [2, 82], 65: [2, 82], 72: [2, 82], 80: [2, 82], 81: [2, 82], 82: [2, 82], 83: [2, 82], 84: [2, 82], 85: [2, 82] }, { 25: 53, 38: 55, 39: [1, 57], 43: 56, 44: [1, 58], 45: 54, 47: [2, 54] }, { 28: 59, 43: 60, 44: [1, 58], 47: [2, 56] }, { 13: 62, 15: [1, 20], 18: [1, 61] }, { 33: [2, 86], 57: 63, 65: [2, 86], 72: [2, 86], 80: [2, 86], 81: [2, 86], 82: [2, 86], 83: [2, 86], 84: [2, 86], 85: [2, 86] }, { 33: [2, 40], 65: [2, 40], 72: [2, 40], 80: [2, 40], 81: [2, 40], 82: [2, 40], 83: [2, 40], 84: [2, 40], 85: [2, 40] }, { 33: [2, 41], 65: [2, 41], 72: [2, 41], 80: [2, 41], 81: [2, 41], 82: [2, 41], 83: [2, 41], 84: [2, 41], 85: [2, 41] }, { 20: 64, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 26: 65, 47: [1, 66] }, { 30: 67, 33: [2, 58], 65: [2, 58], 72: [2, 58], 75: [2, 58], 80: [2, 58], 81: [2, 58], 82: [2, 58], 83: [2, 58], 84: [2, 58], 85: [2, 58] }, { 33: [2, 64], 35: 68, 65: [2, 64], 72: [2, 64], 75: [2, 64], 80: [2, 64], 81: [2, 64], 82: [2, 64], 83: [2, 64], 84: [2, 64], 85: [2, 64] }, { 21: 69, 23: [2, 50], 65: [2, 50], 72: [2, 50], 80: [2, 50], 81: [2, 50], 82: [2, 50], 83: [2, 50], 84: [2, 50], 85: [2, 50] }, { 33: [2, 90], 61: 70, 65: [2, 90], 72: [2, 90], 80: [2, 90], 81: [2, 90], 82: [2, 90], 83: [2, 90], 84: [2, 90], 85: [2, 90] }, { 20: 74, 33: [2, 80], 50: 71, 63: 72, 64: 75, 65: [1, 43], 69: 73, 70: 76, 71: 77, 72: [1, 78], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 72: [1, 79] }, { 23: [2, 42], 33: [2, 42], 54: [2, 42], 65: [2, 42], 68: [2, 42], 72: [2, 42], 75: [2, 42], 80: [2, 42], 81: [2, 42], 82: [2, 42], 83: [2, 42], 84: [2, 42], 85: [2, 42], 87: [1, 50] }, { 20: 74, 53: 80, 54: [2, 84], 63: 81, 64: 75, 65: [1, 43], 69: 82, 70: 76, 71: 77, 72: [1, 78], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 26: 83, 47: [1, 66] }, { 47: [2, 55] }, { 4: 84, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 39: [2, 46], 44: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 47: [2, 20] }, { 20: 85, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 4: 86, 6: 3, 14: [2, 46], 15: [2, 46], 19: [2, 46], 29: [2, 46], 34: [2, 46], 47: [2, 46], 48: [2, 46], 51: [2, 46], 55: [2, 46], 60: [2, 46] }, { 26: 87, 47: [1, 66] }, { 47: [2, 57] }, { 5: [2, 11], 14: [2, 11], 15: [2, 11], 19: [2, 11], 29: [2, 11], 34: [2, 11], 39: [2, 11], 44: [2, 11], 47: [2, 11], 48: [2, 11], 51: [2, 11], 55: [2, 11], 60: [2, 11] }, { 15: [2, 49], 18: [2, 49] }, { 20: 74, 33: [2, 88], 58: 88, 63: 89, 64: 75, 65: [1, 43], 69: 90, 70: 76, 71: 77, 72: [1, 78], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 65: [2, 94], 66: 91, 68: [2, 94], 72: [2, 94], 80: [2, 94], 81: [2, 94], 82: [2, 94], 83: [2, 94], 84: [2, 94], 85: [2, 94] }, { 5: [2, 25], 14: [2, 25], 15: [2, 25], 19: [2, 25], 29: [2, 25], 34: [2, 25], 39: [2, 25], 44: [2, 25], 47: [2, 25], 48: [2, 25], 51: [2, 25], 55: [2, 25], 60: [2, 25] }, { 20: 92, 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 74, 31: 93, 33: [2, 60], 63: 94, 64: 75, 65: [1, 43], 69: 95, 70: 76, 71: 77, 72: [1, 78], 75: [2, 60], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 74, 33: [2, 66], 36: 96, 63: 97, 64: 75, 65: [1, 43], 69: 98, 70: 76, 71: 77, 72: [1, 78], 75: [2, 66], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 74, 22: 99, 23: [2, 52], 63: 100, 64: 75, 65: [1, 43], 69: 101, 70: 76, 71: 77, 72: [1, 78], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 20: 74, 33: [2, 92], 62: 102, 63: 103, 64: 75, 65: [1, 43], 69: 104, 70: 76, 71: 77, 72: [1, 78], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [1, 105] }, { 33: [2, 79], 65: [2, 79], 72: [2, 79], 80: [2, 79], 81: [2, 79], 82: [2, 79], 83: [2, 79], 84: [2, 79], 85: [2, 79] }, { 33: [2, 81] }, { 23: [2, 27], 33: [2, 27], 54: [2, 27], 65: [2, 27], 68: [2, 27], 72: [2, 27], 75: [2, 27], 80: [2, 27], 81: [2, 27], 82: [2, 27], 83: [2, 27], 84: [2, 27], 85: [2, 27] }, { 23: [2, 28], 33: [2, 28], 54: [2, 28], 65: [2, 28], 68: [2, 28], 72: [2, 28], 75: [2, 28], 80: [2, 28], 81: [2, 28], 82: [2, 28], 83: [2, 28], 84: [2, 28], 85: [2, 28] }, { 23: [2, 30], 33: [2, 30], 54: [2, 30], 68: [2, 30], 71: 106, 72: [1, 107], 75: [2, 30] }, { 23: [2, 98], 33: [2, 98], 54: [2, 98], 68: [2, 98], 72: [2, 98], 75: [2, 98] }, { 23: [2, 45], 33: [2, 45], 54: [2, 45], 65: [2, 45], 68: [2, 45], 72: [2, 45], 73: [1, 108], 75: [2, 45], 80: [2, 45], 81: [2, 45], 82: [2, 45], 83: [2, 45], 84: [2, 45], 85: [2, 45], 87: [2, 45] }, { 23: [2, 44], 33: [2, 44], 54: [2, 44], 65: [2, 44], 68: [2, 44], 72: [2, 44], 75: [2, 44], 80: [2, 44], 81: [2, 44], 82: [2, 44], 83: [2, 44], 84: [2, 44], 85: [2, 44], 87: [2, 44] }, { 54: [1, 109] }, { 54: [2, 83], 65: [2, 83], 72: [2, 83], 80: [2, 83], 81: [2, 83], 82: [2, 83], 83: [2, 83], 84: [2, 83], 85: [2, 83] }, { 54: [2, 85] }, { 5: [2, 13], 14: [2, 13], 15: [2, 13], 19: [2, 13], 29: [2, 13], 34: [2, 13], 39: [2, 13], 44: [2, 13], 47: [2, 13], 48: [2, 13], 51: [2, 13], 55: [2, 13], 60: [2, 13] }, { 38: 55, 39: [1, 57], 43: 56, 44: [1, 58], 45: 111, 46: 110, 47: [2, 76] }, { 33: [2, 70], 40: 112, 65: [2, 70], 72: [2, 70], 75: [2, 70], 80: [2, 70], 81: [2, 70], 82: [2, 70], 83: [2, 70], 84: [2, 70], 85: [2, 70] }, { 47: [2, 18] }, { 5: [2, 14], 14: [2, 14], 15: [2, 14], 19: [2, 14], 29: [2, 14], 34: [2, 14], 39: [2, 14], 44: [2, 14], 47: [2, 14], 48: [2, 14], 51: [2, 14], 55: [2, 14], 60: [2, 14] }, { 33: [1, 113] }, { 33: [2, 87], 65: [2, 87], 72: [2, 87], 80: [2, 87], 81: [2, 87], 82: [2, 87], 83: [2, 87], 84: [2, 87], 85: [2, 87] }, { 33: [2, 89] }, { 20: 74, 63: 115, 64: 75, 65: [1, 43], 67: 114, 68: [2, 96], 69: 116, 70: 76, 71: 77, 72: [1, 78], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 33: [1, 117] }, { 32: 118, 33: [2, 62], 74: 119, 75: [1, 120] }, { 33: [2, 59], 65: [2, 59], 72: [2, 59], 75: [2, 59], 80: [2, 59], 81: [2, 59], 82: [2, 59], 83: [2, 59], 84: [2, 59], 85: [2, 59] }, { 33: [2, 61], 75: [2, 61] }, { 33: [2, 68], 37: 121, 74: 122, 75: [1, 120] }, { 33: [2, 65], 65: [2, 65], 72: [2, 65], 75: [2, 65], 80: [2, 65], 81: [2, 65], 82: [2, 65], 83: [2, 65], 84: [2, 65], 85: [2, 65] }, { 33: [2, 67], 75: [2, 67] }, { 23: [1, 123] }, { 23: [2, 51], 65: [2, 51], 72: [2, 51], 80: [2, 51], 81: [2, 51], 82: [2, 51], 83: [2, 51], 84: [2, 51], 85: [2, 51] }, { 23: [2, 53] }, { 33: [1, 124] }, { 33: [2, 91], 65: [2, 91], 72: [2, 91], 80: [2, 91], 81: [2, 91], 82: [2, 91], 83: [2, 91], 84: [2, 91], 85: [2, 91] }, { 33: [2, 93] }, { 5: [2, 22], 14: [2, 22], 15: [2, 22], 19: [2, 22], 29: [2, 22], 34: [2, 22], 39: [2, 22], 44: [2, 22], 47: [2, 22], 48: [2, 22], 51: [2, 22], 55: [2, 22], 60: [2, 22] }, { 23: [2, 99], 33: [2, 99], 54: [2, 99], 68: [2, 99], 72: [2, 99], 75: [2, 99] }, { 73: [1, 108] }, { 20: 74, 63: 125, 64: 75, 65: [1, 43], 72: [1, 35], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 5: [2, 23], 14: [2, 23], 15: [2, 23], 19: [2, 23], 29: [2, 23], 34: [2, 23], 39: [2, 23], 44: [2, 23], 47: [2, 23], 48: [2, 23], 51: [2, 23], 55: [2, 23], 60: [2, 23] }, { 47: [2, 19] }, { 47: [2, 77] }, { 20: 74, 33: [2, 72], 41: 126, 63: 127, 64: 75, 65: [1, 43], 69: 128, 70: 76, 71: 77, 72: [1, 78], 75: [2, 72], 78: 26, 79: 27, 80: [1, 28], 81: [1, 29], 82: [1, 30], 83: [1, 31], 84: [1, 32], 85: [1, 34], 86: 33 }, { 5: [2, 24], 14: [2, 24], 15: [2, 24], 19: [2, 24], 29: [2, 24], 34: [2, 24], 39: [2, 24], 44: [2, 24], 47: [2, 24], 48: [2, 24], 51: [2, 24], 55: [2, 24], 60: [2, 24] }, { 68: [1, 129] }, { 65: [2, 95], 68: [2, 95], 72: [2, 95], 80: [2, 95], 81: [2, 95], 82: [2, 95], 83: [2, 95], 84: [2, 95], 85: [2, 95] }, { 68: [2, 97] }, { 5: [2, 21], 14: [2, 21], 15: [2, 21], 19: [2, 21], 29: [2, 21], 34: [2, 21], 39: [2, 21], 44: [2, 21], 47: [2, 21], 48: [2, 21], 51: [2, 21], 55: [2, 21], 60: [2, 21] }, { 33: [1, 130] }, { 33: [2, 63] }, { 72: [1, 132], 76: 131 }, { 33: [1, 133] }, { 33: [2, 69] }, { 15: [2, 12], 18: [2, 12] }, { 14: [2, 26], 15: [2, 26], 19: [2, 26], 29: [2, 26], 34: [2, 26], 47: [2, 26], 48: [2, 26], 51: [2, 26], 55: [2, 26], 60: [2, 26] }, { 23: [2, 31], 33: [2, 31], 54: [2, 31], 68: [2, 31], 72: [2, 31], 75: [2, 31] }, { 33: [2, 74], 42: 134, 74: 135, 75: [1, 120] }, { 33: [2, 71], 65: [2, 71], 72: [2, 71], 75: [2, 71], 80: [2, 71], 81: [2, 71], 82: [2, 71], 83: [2, 71], 84: [2, 71], 85: [2, 71] }, { 33: [2, 73], 75: [2, 73] }, { 23: [2, 29], 33: [2, 29], 54: [2, 29], 65: [2, 29], 68: [2, 29], 72: [2, 29], 75: [2, 29], 80: [2, 29], 81: [2, 29], 82: [2, 29], 83: [2, 29], 84: [2, 29], 85: [2, 29] }, { 14: [2, 15], 15: [2, 15], 19: [2, 15], 29: [2, 15], 34: [2, 15], 39: [2, 15], 44: [2, 15], 47: [2, 15], 48: [2, 15], 51: [2, 15], 55: [2, 15], 60: [2, 15] }, { 72: [1, 137], 77: [1, 136] }, { 72: [2, 100], 77: [2, 100] }, { 14: [2, 16], 15: [2, 16], 19: [2, 16], 29: [2, 16], 34: [2, 16], 44: [2, 16], 47: [2, 16], 48: [2, 16], 51: [2, 16], 55: [2, 16], 60: [2, 16] }, { 33: [1, 138] }, { 33: [2, 75] }, { 33: [2, 32] }, { 72: [2, 101], 77: [2, 101] }, { 14: [2, 17], 15: [2, 17], 19: [2, 17], 29: [2, 17], 34: [2, 17], 39: [2, 17], 44: [2, 17], 47: [2, 17], 48: [2, 17], 51: [2, 17], 55: [2, 17], 60: [2, 17] }], - defaultActions: { 4: [2, 1], 54: [2, 55], 56: [2, 20], 60: [2, 57], 73: [2, 81], 82: [2, 85], 86: [2, 18], 90: [2, 89], 101: [2, 53], 104: [2, 93], 110: [2, 19], 111: [2, 77], 116: [2, 97], 119: [2, 63], 122: [2, 69], 135: [2, 75], 136: [2, 32] }, - parseError: function parseError(str, hash) { - throw new Error(str); - }, - parse: function parse(input) { - var self = this, - stack = [0], - vstack = [null], - lstack = [], - table = this.table, - yytext = "", - yylineno = 0, - yyleng = 0, - recovering = 0, - TERROR = 2, - EOF = 1; - this.lexer.setInput(input); - this.lexer.yy = this.yy; - this.yy.lexer = this.lexer; - this.yy.parser = this; - if (typeof this.lexer.yylloc == "undefined") this.lexer.yylloc = {}; - var yyloc = this.lexer.yylloc; - lstack.push(yyloc); - var ranges = this.lexer.options && this.lexer.options.ranges; - if (typeof this.yy.parseError === "function") this.parseError = this.yy.parseError; - function popStack(n) { - stack.length = stack.length - 2 * n; - vstack.length = vstack.length - n; - lstack.length = lstack.length - n; - } - function lex() { - var token; - token = self.lexer.lex() || 1; - if (typeof token !== "number") { - token = self.symbols_[token] || token; - } - return token; - } - var symbol, - preErrorSymbol, - state, - action, - a, - r, - yyval = {}, - p, - len, - newState, - expected; - while (true) { - state = stack[stack.length - 1]; - if (this.defaultActions[state]) { - action = this.defaultActions[state]; - } else { - if (symbol === null || typeof symbol == "undefined") { - symbol = lex(); - } - action = table[state] && table[state][symbol]; - } - if (typeof action === "undefined" || !action.length || !action[0]) { - var errStr = ""; - if (!recovering) { - expected = []; - for (p in table[state]) if (this.terminals_[p] && p > 2) { - expected.push("'" + this.terminals_[p] + "'"); - } - if (this.lexer.showPosition) { - errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'"; - } else { - errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1 ? "end of input" : "'" + (this.terminals_[symbol] || symbol) + "'"); - } - this.parseError(errStr, { text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected }); - } - } - if (action[0] instanceof Array && action.length > 1) { - throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol); - } - switch (action[0]) { - case 1: - stack.push(symbol); - vstack.push(this.lexer.yytext); - lstack.push(this.lexer.yylloc); - stack.push(action[1]); - symbol = null; - if (!preErrorSymbol) { - yyleng = this.lexer.yyleng; - yytext = this.lexer.yytext; - yylineno = this.lexer.yylineno; - yyloc = this.lexer.yylloc; - if (recovering > 0) recovering--; - } else { - symbol = preErrorSymbol; - preErrorSymbol = null; - } - break; - case 2: - len = this.productions_[action[1]][1]; - yyval.$ = vstack[vstack.length - len]; - yyval._$ = { first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column }; - if (ranges) { - yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]]; - } - r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); - if (typeof r !== "undefined") { - return r; - } - if (len) { - stack = stack.slice(0, -1 * len * 2); - vstack = vstack.slice(0, -1 * len); - lstack = lstack.slice(0, -1 * len); - } - stack.push(this.productions_[action[1]][0]); - vstack.push(yyval.$); - lstack.push(yyval._$); - newState = table[stack[stack.length - 2]][stack[stack.length - 1]]; - stack.push(newState); - break; - case 3: - return true; - } - } - return true; - } - }; - /* Jison generated lexer */ - var lexer = (function () { - var lexer = { EOF: 1, - parseError: function parseError(str, hash) { - if (this.yy.parser) { - this.yy.parser.parseError(str, hash); - } else { - throw new Error(str); - } - }, - setInput: function setInput(input) { - this._input = input; - this._more = this._less = this.done = false; - this.yylineno = this.yyleng = 0; - this.yytext = this.matched = this.match = ''; - this.conditionStack = ['INITIAL']; - this.yylloc = { first_line: 1, first_column: 0, last_line: 1, last_column: 0 }; - if (this.options.ranges) this.yylloc.range = [0, 0]; - this.offset = 0; - return this; - }, - input: function input() { - var ch = this._input[0]; - this.yytext += ch; - this.yyleng++; - this.offset++; - this.match += ch; - this.matched += ch; - var lines = ch.match(/(?:\r\n?|\n).*/g); - if (lines) { - this.yylineno++; - this.yylloc.last_line++; - } else { - this.yylloc.last_column++; - } - if (this.options.ranges) this.yylloc.range[1]++; - - this._input = this._input.slice(1); - return ch; - }, - unput: function unput(ch) { - var len = ch.length; - var lines = ch.split(/(?:\r\n?|\n)/g); - - this._input = ch + this._input; - this.yytext = this.yytext.substr(0, this.yytext.length - len - 1); - //this.yyleng -= len; - this.offset -= len; - var oldLines = this.match.split(/(?:\r\n?|\n)/g); - this.match = this.match.substr(0, this.match.length - 1); - this.matched = this.matched.substr(0, this.matched.length - 1); - - if (lines.length - 1) this.yylineno -= lines.length - 1; - var r = this.yylloc.range; - - this.yylloc = { first_line: this.yylloc.first_line, - last_line: this.yylineno + 1, - first_column: this.yylloc.first_column, - last_column: lines ? (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length : this.yylloc.first_column - len - }; - - if (this.options.ranges) { - this.yylloc.range = [r[0], r[0] + this.yyleng - len]; - } - return this; - }, - more: function more() { - this._more = true; - return this; - }, - less: function less(n) { - this.unput(this.match.slice(n)); - }, - pastInput: function pastInput() { - var past = this.matched.substr(0, this.matched.length - this.match.length); - return (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, ""); - }, - upcomingInput: function upcomingInput() { - var next = this.match; - if (next.length < 20) { - next += this._input.substr(0, 20 - next.length); - } - return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(/\n/g, ""); - }, - showPosition: function showPosition() { - var pre = this.pastInput(); - var c = new Array(pre.length + 1).join("-"); - return pre + this.upcomingInput() + "\n" + c + "^"; - }, - next: function next() { - if (this.done) { - return this.EOF; - } - if (!this._input) this.done = true; - - var token, match, tempMatch, index, col, lines; - if (!this._more) { - this.yytext = ''; - this.match = ''; - } - var rules = this._currentRules(); - for (var i = 0; i < rules.length; i++) { - tempMatch = this._input.match(this.rules[rules[i]]); - if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { - match = tempMatch; - index = i; - if (!this.options.flex) break; - } - } - if (match) { - lines = match[0].match(/(?:\r\n?|\n).*/g); - if (lines) this.yylineno += lines.length; - this.yylloc = { first_line: this.yylloc.last_line, - last_line: this.yylineno + 1, - first_column: this.yylloc.last_column, - last_column: lines ? lines[lines.length - 1].length - lines[lines.length - 1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length }; - this.yytext += match[0]; - this.match += match[0]; - this.matches = match; - this.yyleng = this.yytext.length; - if (this.options.ranges) { - this.yylloc.range = [this.offset, this.offset += this.yyleng]; - } - this._more = false; - this._input = this._input.slice(match[0].length); - this.matched += match[0]; - token = this.performAction.call(this, this.yy, this, rules[index], this.conditionStack[this.conditionStack.length - 1]); - if (this.done && this._input) this.done = false; - if (token) return token;else return; - } - if (this._input === "") { - return this.EOF; - } else { - return this.parseError('Lexical error on line ' + (this.yylineno + 1) + '. Unrecognized text.\n' + this.showPosition(), { text: "", token: null, line: this.yylineno }); - } - }, - lex: function lex() { - var r = this.next(); - if (typeof r !== 'undefined') { - return r; - } else { - return this.lex(); - } - }, - begin: function begin(condition) { - this.conditionStack.push(condition); - }, - popState: function popState() { - return this.conditionStack.pop(); - }, - _currentRules: function _currentRules() { - return this.conditions[this.conditionStack[this.conditionStack.length - 1]].rules; - }, - topState: function topState() { - return this.conditionStack[this.conditionStack.length - 2]; - }, - pushState: function begin(condition) { - this.begin(condition); - } }; - lexer.options = {}; - lexer.performAction = function anonymous(yy, yy_, $avoiding_name_collisions, YY_START) { - - function strip(start, end) { - return yy_.yytext = yy_.yytext.substring(start, yy_.yyleng - end + start); - } - - var YYSTATE = YY_START; - switch ($avoiding_name_collisions) { - case 0: - if (yy_.yytext.slice(-2) === "\\\\") { - strip(0, 1); - this.begin("mu"); - } else if (yy_.yytext.slice(-1) === "\\") { - strip(0, 1); - this.begin("emu"); - } else { - this.begin("mu"); - } - if (yy_.yytext) return 15; - - break; - case 1: - return 15; - break; - case 2: - this.popState(); - return 15; - - break; - case 3: - this.begin('raw');return 15; - break; - case 4: - this.popState(); - // Should be using `this.topState()` below, but it currently - // returns the second top instead of the first top. Opened an - // issue about it at https://github.com/zaach/jison/issues/291 - if (this.conditionStack[this.conditionStack.length - 1] === 'raw') { - return 15; - } else { - strip(5, 9); - return 'END_RAW_BLOCK'; - } - - break; - case 5: - return 15; - break; - case 6: - this.popState(); - return 14; - - break; - case 7: - return 65; - break; - case 8: - return 68; - break; - case 9: - return 19; - break; - case 10: - this.popState(); - this.begin('raw'); - return 23; - - break; - case 11: - return 55; - break; - case 12: - return 60; - break; - case 13: - return 29; - break; - case 14: - return 47; - break; - case 15: - this.popState();return 44; - break; - case 16: - this.popState();return 44; - break; - case 17: - return 34; - break; - case 18: - return 39; - break; - case 19: - return 51; - break; - case 20: - return 48; - break; - case 21: - this.unput(yy_.yytext); - this.popState(); - this.begin('com'); - - break; - case 22: - this.popState(); - return 14; - - break; - case 23: - return 48; - break; - case 24: - return 73; - break; - case 25: - return 72; - break; - case 26: - return 72; - break; - case 27: - return 87; - break; - case 28: - // ignore whitespace - break; - case 29: - this.popState();return 54; - break; - case 30: - this.popState();return 33; - break; - case 31: - yy_.yytext = strip(1, 2).replace(/\\"/g, '"');return 80; - break; - case 32: - yy_.yytext = strip(1, 2).replace(/\\'/g, "'");return 80; - break; - case 33: - return 85; - break; - case 34: - return 82; - break; - case 35: - return 82; - break; - case 36: - return 83; - break; - case 37: - return 84; - break; - case 38: - return 81; - break; - case 39: - return 75; - break; - case 40: - return 77; - break; - case 41: - return 72; - break; - case 42: - yy_.yytext = yy_.yytext.replace(/\\([\\\]])/g, '$1');return 72; - break; - case 43: - return 'INVALID'; - break; - case 44: - return 5; - break; - } - }; - lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/, /^(?:[^\x00]+)/, /^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/, /^(?:\{\{\{\{(?=[^\/]))/, /^(?:\{\{\{\{\/[^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=[=}\s\/.])\}\}\}\})/, /^(?:[^\x00]+?(?=(\{\{\{\{)))/, /^(?:[\s\S]*?--(~)?\}\})/, /^(?:\()/, /^(?:\))/, /^(?:\{\{\{\{)/, /^(?:\}\}\}\})/, /^(?:\{\{(~)?>)/, /^(?:\{\{(~)?#>)/, /^(?:\{\{(~)?#\*?)/, /^(?:\{\{(~)?\/)/, /^(?:\{\{(~)?\^\s*(~)?\}\})/, /^(?:\{\{(~)?\s*else\s*(~)?\}\})/, /^(?:\{\{(~)?\^)/, /^(?:\{\{(~)?\s*else\b)/, /^(?:\{\{(~)?\{)/, /^(?:\{\{(~)?&)/, /^(?:\{\{(~)?!--)/, /^(?:\{\{(~)?![\s\S]*?\}\})/, /^(?:\{\{(~)?\*?)/, /^(?:=)/, /^(?:\.\.)/, /^(?:\.(?=([=~}\s\/.)|])))/, /^(?:[\/.])/, /^(?:\s+)/, /^(?:\}(~)?\}\})/, /^(?:(~)?\}\})/, /^(?:"(\\["]|[^"])*")/, /^(?:'(\\[']|[^'])*')/, /^(?:@)/, /^(?:true(?=([~}\s)])))/, /^(?:false(?=([~}\s)])))/, /^(?:undefined(?=([~}\s)])))/, /^(?:null(?=([~}\s)])))/, /^(?:-?[0-9]+(?:\.[0-9]+)?(?=([~}\s)])))/, /^(?:as\s+\|)/, /^(?:\|)/, /^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.)|]))))/, /^(?:\[(\\\]|[^\]])*\])/, /^(?:.)/, /^(?:$)/]; - lexer.conditions = { "mu": { "rules": [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44], "inclusive": false }, "emu": { "rules": [2], "inclusive": false }, "com": { "rules": [6], "inclusive": false }, "raw": { "rules": [3, 4, 5], "inclusive": false }, "INITIAL": { "rules": [0, 1, 44], "inclusive": true } }; - return lexer; - })(); - parser.lexer = lexer; - function Parser() { - this.yy = {}; - }Parser.prototype = parser;parser.Parser = Parser; - return new Parser(); - })();exports["default"] = handlebars; - module.exports = exports["default"]; - -/***/ }), -/* 48 */ -/***/ (function(module, exports, __webpack_require__) { - - 'use strict'; - - var _interopRequireDefault = __webpack_require__(1)['default']; - - exports.__esModule = true; - - var _visitor = __webpack_require__(49); - - var _visitor2 = _interopRequireDefault(_visitor); - - function WhitespaceControl() { - var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; - - this.options = options; - } - WhitespaceControl.prototype = new _visitor2['default'](); - - WhitespaceControl.prototype.Program = function (program) { - var doStandalone = !this.options.ignoreStandalone; - - var isRoot = !this.isRootSeen; - this.isRootSeen = true; - - var body = program.body; - for (var i = 0, l = body.length; i < l; i++) { - var current = body[i], - strip = this.accept(current); - - if (!strip) { - continue; - } - - var _isPrevWhitespace = isPrevWhitespace(body, i, isRoot), - _isNextWhitespace = isNextWhitespace(body, i, isRoot), - openStandalone = strip.openStandalone && _isPrevWhitespace, - closeStandalone = strip.closeStandalone && _isNextWhitespace, - inlineStandalone = strip.inlineStandalone && _isPrevWhitespace && _isNextWhitespace; - - if (strip.close) { - omitRight(body, i, true); - } - if (strip.open) { - omitLeft(body, i, true); - } - - if (doStandalone && inlineStandalone) { - omitRight(body, i); - - if (omitLeft(body, i)) { - // If we are on a standalone node, save the indent info for partials - if (current.type === 'PartialStatement') { - // Pull out the whitespace from the final line - current.indent = /([ \t]+$)/.exec(body[i - 1].original)[1]; - } - } - } - if (doStandalone && openStandalone) { - omitRight((current.program || current.inverse).body); - - // Strip out the previous content node if it's whitespace only - omitLeft(body, i); - } - if (doStandalone && closeStandalone) { - // Always strip the next node - omitRight(body, i); - - omitLeft((current.inverse || current.program).body); - } - } - - return program; - }; - - WhitespaceControl.prototype.BlockStatement = WhitespaceControl.prototype.DecoratorBlock = WhitespaceControl.prototype.PartialBlockStatement = function (block) { - this.accept(block.program); - this.accept(block.inverse); - - // Find the inverse program that is involed with whitespace stripping. - var program = block.program || block.inverse, - inverse = block.program && block.inverse, - firstInverse = inverse, - lastInverse = inverse; - - if (inverse && inverse.chained) { - firstInverse = inverse.body[0].program; - - // Walk the inverse chain to find the last inverse that is actually in the chain. - while (lastInverse.chained) { - lastInverse = lastInverse.body[lastInverse.body.length - 1].program; - } - } - - var strip = { - open: block.openStrip.open, - close: block.closeStrip.close, - - // Determine the standalone candiacy. Basically flag our content as being possibly standalone - // so our parent can determine if we actually are standalone - openStandalone: isNextWhitespace(program.body), - closeStandalone: isPrevWhitespace((firstInverse || program).body) - }; - - if (block.openStrip.close) { - omitRight(program.body, null, true); - } - - if (inverse) { - var inverseStrip = block.inverseStrip; - - if (inverseStrip.open) { - omitLeft(program.body, null, true); - } - - if (inverseStrip.close) { - omitRight(firstInverse.body, null, true); - } - if (block.closeStrip.open) { - omitLeft(lastInverse.body, null, true); - } - - // Find standalone else statments - if (!this.options.ignoreStandalone && isPrevWhitespace(program.body) && isNextWhitespace(firstInverse.body)) { - omitLeft(program.body); - omitRight(firstInverse.body); - } - } else if (block.closeStrip.open) { - omitLeft(program.body, null, true); - } - - return strip; - }; - - WhitespaceControl.prototype.Decorator = WhitespaceControl.prototype.MustacheStatement = function (mustache) { - return mustache.strip; - }; - - WhitespaceControl.prototype.PartialStatement = WhitespaceControl.prototype.CommentStatement = function (node) { - /* istanbul ignore next */ - var strip = node.strip || {}; - return { - inlineStandalone: true, - open: strip.open, - close: strip.close - }; - }; - - function isPrevWhitespace(body, i, isRoot) { - if (i === undefined) { - i = body.length; - } - - // Nodes that end with newlines are considered whitespace (but are special - // cased for strip operations) - var prev = body[i - 1], - sibling = body[i - 2]; - if (!prev) { - return isRoot; - } - - if (prev.type === 'ContentStatement') { - return (sibling || !isRoot ? /\r?\n\s*?$/ : /(^|\r?\n)\s*?$/).test(prev.original); - } - } - function isNextWhitespace(body, i, isRoot) { - if (i === undefined) { - i = -1; - } - - var next = body[i + 1], - sibling = body[i + 2]; - if (!next) { - return isRoot; - } - - if (next.type === 'ContentStatement') { - return (sibling || !isRoot ? /^\s*?\r?\n/ : /^\s*?(\r?\n|$)/).test(next.original); - } - } - - // Marks the node to the right of the position as omitted. - // I.e. {{foo}}' ' will mark the ' ' node as omitted. - // - // If i is undefined, then the first child will be marked as such. - // - // If mulitple is truthy then all whitespace will be stripped out until non-whitespace - // content is met. - function omitRight(body, i, multiple) { - var current = body[i == null ? 0 : i + 1]; - if (!current || current.type !== 'ContentStatement' || !multiple && current.rightStripped) { - return; - } - - var original = current.value; - current.value = current.value.replace(multiple ? /^\s+/ : /^[ \t]*\r?\n?/, ''); - current.rightStripped = current.value !== original; - } - - // Marks the node to the left of the position as omitted. - // I.e. ' '{{foo}} will mark the ' ' node as omitted. - // - // If i is undefined then the last child will be marked as such. - // - // If mulitple is truthy then all whitespace will be stripped out until non-whitespace - // content is met. - function omitLeft(body, i, multiple) { - var current = body[i == null ? body.length - 1 : i - 1]; - if (!current || current.type !== 'ContentStatement' || !multiple && current.leftStripped) { - return; - } - - // We omit the last node if it's whitespace only and not preceded by a non-content node. - var original = current.value; - current.value = current.value.replace(multiple ? /\s+$/ : /[ \t]+$/, ''); - current.leftStripped = current.value !== original; - return current.leftStripped; - } - - exports['default'] = WhitespaceControl; - module.exports = exports['default']; - -/***/ }), -/* 49 */ -/***/ (function(module, exports, __webpack_require__) { - - 'use strict'; - - var _interopRequireDefault = __webpack_require__(1)['default']; - - exports.__esModule = true; - - var _exception = __webpack_require__(6); - - var _exception2 = _interopRequireDefault(_exception); - - function Visitor() { - this.parents = []; - } - - Visitor.prototype = { - constructor: Visitor, - mutating: false, - - // Visits a given value. If mutating, will replace the value if necessary. - acceptKey: function acceptKey(node, name) { - var value = this.accept(node[name]); - if (this.mutating) { - // Hacky sanity check: This may have a few false positives for type for the helper - // methods but will generally do the right thing without a lot of overhead. - if (value && !Visitor.prototype[value.type]) { - throw new _exception2['default']('Unexpected node type "' + value.type + '" found when accepting ' + name + ' on ' + node.type); - } - node[name] = value; - } - }, - - // Performs an accept operation with added sanity check to ensure - // required keys are not removed. - acceptRequired: function acceptRequired(node, name) { - this.acceptKey(node, name); - - if (!node[name]) { - throw new _exception2['default'](node.type + ' requires ' + name); - } - }, - - // Traverses a given array. If mutating, empty respnses will be removed - // for child elements. - acceptArray: function acceptArray(array) { - for (var i = 0, l = array.length; i < l; i++) { - this.acceptKey(array, i); - - if (!array[i]) { - array.splice(i, 1); - i--; - l--; - } - } - }, - - accept: function accept(object) { - if (!object) { - return; - } - - /* istanbul ignore next: Sanity code */ - if (!this[object.type]) { - throw new _exception2['default']('Unknown type: ' + object.type, object); - } - - if (this.current) { - this.parents.unshift(this.current); - } - this.current = object; - - var ret = this[object.type](object); - - this.current = this.parents.shift(); - - if (!this.mutating || ret) { - return ret; - } else if (ret !== false) { - return object; - } - }, - - Program: function Program(program) { - this.acceptArray(program.body); - }, - - MustacheStatement: visitSubExpression, - Decorator: visitSubExpression, - - BlockStatement: visitBlock, - DecoratorBlock: visitBlock, - - PartialStatement: visitPartial, - PartialBlockStatement: function PartialBlockStatement(partial) { - visitPartial.call(this, partial); - - this.acceptKey(partial, 'program'); - }, - - ContentStatement: function ContentStatement() /* content */{}, - CommentStatement: function CommentStatement() /* comment */{}, - - SubExpression: visitSubExpression, - - PathExpression: function PathExpression() /* path */{}, - - StringLiteral: function StringLiteral() /* string */{}, - NumberLiteral: function NumberLiteral() /* number */{}, - BooleanLiteral: function BooleanLiteral() /* bool */{}, - UndefinedLiteral: function UndefinedLiteral() /* literal */{}, - NullLiteral: function NullLiteral() /* literal */{}, - - Hash: function Hash(hash) { - this.acceptArray(hash.pairs); - }, - HashPair: function HashPair(pair) { - this.acceptRequired(pair, 'value'); - } - }; - - function visitSubExpression(mustache) { - this.acceptRequired(mustache, 'path'); - this.acceptArray(mustache.params); - this.acceptKey(mustache, 'hash'); - } - function visitBlock(block) { - visitSubExpression.call(this, block); - - this.acceptKey(block, 'program'); - this.acceptKey(block, 'inverse'); - } - function visitPartial(partial) { - this.acceptRequired(partial, 'name'); - this.acceptArray(partial.params); - this.acceptKey(partial, 'hash'); - } - - exports['default'] = Visitor; - module.exports = exports['default']; - -/***/ }), -/* 50 */ -/***/ (function(module, exports, __webpack_require__) { - - 'use strict'; - - var _interopRequireDefault = __webpack_require__(1)['default']; - - exports.__esModule = true; - exports.SourceLocation = SourceLocation; - exports.id = id; - exports.stripFlags = stripFlags; - exports.stripComment = stripComment; - exports.preparePath = preparePath; - exports.prepareMustache = prepareMustache; - exports.prepareRawBlock = prepareRawBlock; - exports.prepareBlock = prepareBlock; - exports.prepareProgram = prepareProgram; - exports.preparePartialBlock = preparePartialBlock; - - var _exception = __webpack_require__(6); - - var _exception2 = _interopRequireDefault(_exception); - - function validateClose(open, close) { - close = close.path ? close.path.original : close; - - if (open.path.original !== close) { - var errorNode = { loc: open.path.loc }; - - throw new _exception2['default'](open.path.original + " doesn't match " + close, errorNode); - } - } - - function SourceLocation(source, locInfo) { - this.source = source; - this.start = { - line: locInfo.first_line, - column: locInfo.first_column - }; - this.end = { - line: locInfo.last_line, - column: locInfo.last_column - }; - } - - function id(token) { - if (/^\[.*\]$/.test(token)) { - return token.substring(1, token.length - 1); - } else { - return token; - } - } - - function stripFlags(open, close) { - return { - open: open.charAt(2) === '~', - close: close.charAt(close.length - 3) === '~' - }; - } - - function stripComment(comment) { - return comment.replace(/^\{\{~?!-?-?/, '').replace(/-?-?~?\}\}$/, ''); - } - - function preparePath(data, parts, loc) { - loc = this.locInfo(loc); - - var original = data ? '@' : '', - dig = [], - depth = 0; - - for (var i = 0, l = parts.length; i < l; i++) { - var part = parts[i].part, - - // If we have [] syntax then we do not treat path references as operators, - // i.e. foo.[this] resolves to approximately context.foo['this'] - isLiteral = parts[i].original !== part; - original += (parts[i].separator || '') + part; - - if (!isLiteral && (part === '..' || part === '.' || part === 'this')) { - if (dig.length > 0) { - throw new _exception2['default']('Invalid path: ' + original, { loc: loc }); - } else if (part === '..') { - depth++; - } - } else { - dig.push(part); - } - } - - return { - type: 'PathExpression', - data: data, - depth: depth, - parts: dig, - original: original, - loc: loc - }; - } - - function prepareMustache(path, params, hash, open, strip, locInfo) { - // Must use charAt to support IE pre-10 - var escapeFlag = open.charAt(3) || open.charAt(2), - escaped = escapeFlag !== '{' && escapeFlag !== '&'; - - var decorator = /\*/.test(open); - return { - type: decorator ? 'Decorator' : 'MustacheStatement', - path: path, - params: params, - hash: hash, - escaped: escaped, - strip: strip, - loc: this.locInfo(locInfo) - }; - } - - function prepareRawBlock(openRawBlock, contents, close, locInfo) { - validateClose(openRawBlock, close); - - locInfo = this.locInfo(locInfo); - var program = { - type: 'Program', - body: contents, - strip: {}, - loc: locInfo - }; - - return { - type: 'BlockStatement', - path: openRawBlock.path, - params: openRawBlock.params, - hash: openRawBlock.hash, - program: program, - openStrip: {}, - inverseStrip: {}, - closeStrip: {}, - loc: locInfo - }; - } - - function prepareBlock(openBlock, program, inverseAndProgram, close, inverted, locInfo) { - if (close && close.path) { - validateClose(openBlock, close); - } - - var decorator = /\*/.test(openBlock.open); - - program.blockParams = openBlock.blockParams; - - var inverse = undefined, - inverseStrip = undefined; - - if (inverseAndProgram) { - if (decorator) { - throw new _exception2['default']('Unexpected inverse block on decorator', inverseAndProgram); - } - - if (inverseAndProgram.chain) { - inverseAndProgram.program.body[0].closeStrip = close.strip; - } - - inverseStrip = inverseAndProgram.strip; - inverse = inverseAndProgram.program; - } - - if (inverted) { - inverted = inverse; - inverse = program; - program = inverted; - } - - return { - type: decorator ? 'DecoratorBlock' : 'BlockStatement', - path: openBlock.path, - params: openBlock.params, - hash: openBlock.hash, - program: program, - inverse: inverse, - openStrip: openBlock.strip, - inverseStrip: inverseStrip, - closeStrip: close && close.strip, - loc: this.locInfo(locInfo) - }; - } - - function prepareProgram(statements, loc) { - if (!loc && statements.length) { - var firstLoc = statements[0].loc, - lastLoc = statements[statements.length - 1].loc; - - /* istanbul ignore else */ - if (firstLoc && lastLoc) { - loc = { - source: firstLoc.source, - start: { - line: firstLoc.start.line, - column: firstLoc.start.column - }, - end: { - line: lastLoc.end.line, - column: lastLoc.end.column - } - }; - } - } - - return { - type: 'Program', - body: statements, - strip: {}, - loc: loc - }; - } - - function preparePartialBlock(open, program, close, locInfo) { - validateClose(open, close); - - return { - type: 'PartialBlockStatement', - name: open.path, - params: open.params, - hash: open.hash, - program: program, - openStrip: open.strip, - closeStrip: close && close.strip, - loc: this.locInfo(locInfo) - }; - } - -/***/ }), -/* 51 */ -/***/ (function(module, exports, __webpack_require__) { - - /* eslint-disable new-cap */ - - 'use strict'; - - var _Object$create = __webpack_require__(34)['default']; - - var _interopRequireDefault = __webpack_require__(1)['default']; - - exports.__esModule = true; - exports.Compiler = Compiler; - exports.precompile = precompile; - exports.compile = compile; - - var _exception = __webpack_require__(6); - - var _exception2 = _interopRequireDefault(_exception); - - var _utils = __webpack_require__(5); - - var _ast = __webpack_require__(45); - - var _ast2 = _interopRequireDefault(_ast); - - var slice = [].slice; - - function Compiler() {} - - // the foundHelper register will disambiguate helper lookup from finding a - // function in a context. This is necessary for mustache compatibility, which - // requires that context functions in blocks are evaluated by blockHelperMissing, - // and then proceed as if the resulting value was provided to blockHelperMissing. - - Compiler.prototype = { - compiler: Compiler, - - equals: function equals(other) { - var len = this.opcodes.length; - if (other.opcodes.length !== len) { - return false; - } - - for (var i = 0; i < len; i++) { - var opcode = this.opcodes[i], - otherOpcode = other.opcodes[i]; - if (opcode.opcode !== otherOpcode.opcode || !argEquals(opcode.args, otherOpcode.args)) { - return false; - } - } - - // We know that length is the same between the two arrays because they are directly tied - // to the opcode behavior above. - len = this.children.length; - for (var i = 0; i < len; i++) { - if (!this.children[i].equals(other.children[i])) { - return false; - } - } - - return true; - }, - - guid: 0, - - compile: function compile(program, options) { - this.sourceNode = []; - this.opcodes = []; - this.children = []; - this.options = options; - this.stringParams = options.stringParams; - this.trackIds = options.trackIds; - - options.blockParams = options.blockParams || []; - - options.knownHelpers = _utils.extend(_Object$create(null), { - helperMissing: true, - blockHelperMissing: true, - each: true, - 'if': true, - unless: true, - 'with': true, - log: true, - lookup: true - }, options.knownHelpers); - - return this.accept(program); - }, - - compileProgram: function compileProgram(program) { - var childCompiler = new this.compiler(), - // eslint-disable-line new-cap - result = childCompiler.compile(program, this.options), - guid = this.guid++; - - this.usePartial = this.usePartial || result.usePartial; - - this.children[guid] = result; - this.useDepths = this.useDepths || result.useDepths; - - return guid; - }, - - accept: function accept(node) { - /* istanbul ignore next: Sanity code */ - if (!this[node.type]) { - throw new _exception2['default']('Unknown type: ' + node.type, node); - } - - this.sourceNode.unshift(node); - var ret = this[node.type](node); - this.sourceNode.shift(); - return ret; - }, - - Program: function Program(program) { - this.options.blockParams.unshift(program.blockParams); - - var body = program.body, - bodyLength = body.length; - for (var i = 0; i < bodyLength; i++) { - this.accept(body[i]); - } - - this.options.blockParams.shift(); - - this.isSimple = bodyLength === 1; - this.blockParams = program.blockParams ? program.blockParams.length : 0; - - return this; - }, - - BlockStatement: function BlockStatement(block) { - transformLiteralToPath(block); - - var program = block.program, - inverse = block.inverse; - - program = program && this.compileProgram(program); - inverse = inverse && this.compileProgram(inverse); - - var type = this.classifySexpr(block); - - if (type === 'helper') { - this.helperSexpr(block, program, inverse); - } else if (type === 'simple') { - this.simpleSexpr(block); - - // now that the simple mustache is resolved, we need to - // evaluate it by executing `blockHelperMissing` - this.opcode('pushProgram', program); - this.opcode('pushProgram', inverse); - this.opcode('emptyHash'); - this.opcode('blockValue', block.path.original); - } else { - this.ambiguousSexpr(block, program, inverse); - - // now that the simple mustache is resolved, we need to - // evaluate it by executing `blockHelperMissing` - this.opcode('pushProgram', program); - this.opcode('pushProgram', inverse); - this.opcode('emptyHash'); - this.opcode('ambiguousBlockValue'); - } - - this.opcode('append'); - }, - - DecoratorBlock: function DecoratorBlock(decorator) { - var program = decorator.program && this.compileProgram(decorator.program); - var params = this.setupFullMustacheParams(decorator, program, undefined), - path = decorator.path; - - this.useDecorators = true; - this.opcode('registerDecorator', params.length, path.original); - }, - - PartialStatement: function PartialStatement(partial) { - this.usePartial = true; - - var program = partial.program; - if (program) { - program = this.compileProgram(partial.program); - } - - var params = partial.params; - if (params.length > 1) { - throw new _exception2['default']('Unsupported number of partial arguments: ' + params.length, partial); - } else if (!params.length) { - if (this.options.explicitPartialContext) { - this.opcode('pushLiteral', 'undefined'); - } else { - params.push({ type: 'PathExpression', parts: [], depth: 0 }); - } - } - - var partialName = partial.name.original, - isDynamic = partial.name.type === 'SubExpression'; - if (isDynamic) { - this.accept(partial.name); - } - - this.setupFullMustacheParams(partial, program, undefined, true); - - var indent = partial.indent || ''; - if (this.options.preventIndent && indent) { - this.opcode('appendContent', indent); - indent = ''; - } - - this.opcode('invokePartial', isDynamic, partialName, indent); - this.opcode('append'); - }, - PartialBlockStatement: function PartialBlockStatement(partialBlock) { - this.PartialStatement(partialBlock); - }, - - MustacheStatement: function MustacheStatement(mustache) { - this.SubExpression(mustache); - - if (mustache.escaped && !this.options.noEscape) { - this.opcode('appendEscaped'); - } else { - this.opcode('append'); - } - }, - Decorator: function Decorator(decorator) { - this.DecoratorBlock(decorator); - }, - - ContentStatement: function ContentStatement(content) { - if (content.value) { - this.opcode('appendContent', content.value); - } - }, - - CommentStatement: function CommentStatement() {}, - - SubExpression: function SubExpression(sexpr) { - transformLiteralToPath(sexpr); - var type = this.classifySexpr(sexpr); - - if (type === 'simple') { - this.simpleSexpr(sexpr); - } else if (type === 'helper') { - this.helperSexpr(sexpr); - } else { - this.ambiguousSexpr(sexpr); - } - }, - ambiguousSexpr: function ambiguousSexpr(sexpr, program, inverse) { - var path = sexpr.path, - name = path.parts[0], - isBlock = program != null || inverse != null; - - this.opcode('getContext', path.depth); - - this.opcode('pushProgram', program); - this.opcode('pushProgram', inverse); - - path.strict = true; - this.accept(path); - - this.opcode('invokeAmbiguous', name, isBlock); - }, - - simpleSexpr: function simpleSexpr(sexpr) { - var path = sexpr.path; - path.strict = true; - this.accept(path); - this.opcode('resolvePossibleLambda'); - }, - - helperSexpr: function helperSexpr(sexpr, program, inverse) { - var params = this.setupFullMustacheParams(sexpr, program, inverse), - path = sexpr.path, - name = path.parts[0]; - - if (this.options.knownHelpers[name]) { - this.opcode('invokeKnownHelper', params.length, name); - } else if (this.options.knownHelpersOnly) { - throw new _exception2['default']('You specified knownHelpersOnly, but used the unknown helper ' + name, sexpr); - } else { - path.strict = true; - path.falsy = true; - - this.accept(path); - this.opcode('invokeHelper', params.length, path.original, _ast2['default'].helpers.simpleId(path)); - } - }, - - PathExpression: function PathExpression(path) { - this.addDepth(path.depth); - this.opcode('getContext', path.depth); - - var name = path.parts[0], - scoped = _ast2['default'].helpers.scopedId(path), - blockParamId = !path.depth && !scoped && this.blockParamIndex(name); - - if (blockParamId) { - this.opcode('lookupBlockParam', blockParamId, path.parts); - } else if (!name) { - // Context reference, i.e. `{{foo .}}` or `{{foo ..}}` - this.opcode('pushContext'); - } else if (path.data) { - this.options.data = true; - this.opcode('lookupData', path.depth, path.parts, path.strict); - } else { - this.opcode('lookupOnContext', path.parts, path.falsy, path.strict, scoped); - } - }, - - StringLiteral: function StringLiteral(string) { - this.opcode('pushString', string.value); - }, - - NumberLiteral: function NumberLiteral(number) { - this.opcode('pushLiteral', number.value); - }, - - BooleanLiteral: function BooleanLiteral(bool) { - this.opcode('pushLiteral', bool.value); - }, - - UndefinedLiteral: function UndefinedLiteral() { - this.opcode('pushLiteral', 'undefined'); - }, - - NullLiteral: function NullLiteral() { - this.opcode('pushLiteral', 'null'); - }, - - Hash: function Hash(hash) { - var pairs = hash.pairs, - i = 0, - l = pairs.length; - - this.opcode('pushHash'); - - for (; i < l; i++) { - this.pushParam(pairs[i].value); - } - while (i--) { - this.opcode('assignToHash', pairs[i].key); - } - this.opcode('popHash'); - }, - - // HELPERS - opcode: function opcode(name) { - this.opcodes.push({ - opcode: name, - args: slice.call(arguments, 1), - loc: this.sourceNode[0].loc - }); - }, - - addDepth: function addDepth(depth) { - if (!depth) { - return; - } - - this.useDepths = true; - }, - - classifySexpr: function classifySexpr(sexpr) { - var isSimple = _ast2['default'].helpers.simpleId(sexpr.path); - - var isBlockParam = isSimple && !!this.blockParamIndex(sexpr.path.parts[0]); - - // a mustache is an eligible helper if: - // * its id is simple (a single part, not `this` or `..`) - var isHelper = !isBlockParam && _ast2['default'].helpers.helperExpression(sexpr); - - // if a mustache is an eligible helper but not a definite - // helper, it is ambiguous, and will be resolved in a later - // pass or at runtime. - var isEligible = !isBlockParam && (isHelper || isSimple); - - // if ambiguous, we can possibly resolve the ambiguity now - // An eligible helper is one that does not have a complex path, i.e. `this.foo`, `../foo` etc. - if (isEligible && !isHelper) { - var _name = sexpr.path.parts[0], - options = this.options; - if (options.knownHelpers[_name]) { - isHelper = true; - } else if (options.knownHelpersOnly) { - isEligible = false; - } - } - - if (isHelper) { - return 'helper'; - } else if (isEligible) { - return 'ambiguous'; - } else { - return 'simple'; - } - }, - - pushParams: function pushParams(params) { - for (var i = 0, l = params.length; i < l; i++) { - this.pushParam(params[i]); - } - }, - - pushParam: function pushParam(val) { - var value = val.value != null ? val.value : val.original || ''; - - if (this.stringParams) { - if (value.replace) { - value = value.replace(/^(\.?\.\/)*/g, '').replace(/\//g, '.'); - } - - if (val.depth) { - this.addDepth(val.depth); - } - this.opcode('getContext', val.depth || 0); - this.opcode('pushStringParam', value, val.type); - - if (val.type === 'SubExpression') { - // SubExpressions get evaluated and passed in - // in string params mode. - this.accept(val); - } - } else { - if (this.trackIds) { - var blockParamIndex = undefined; - if (val.parts && !_ast2['default'].helpers.scopedId(val) && !val.depth) { - blockParamIndex = this.blockParamIndex(val.parts[0]); - } - if (blockParamIndex) { - var blockParamChild = val.parts.slice(1).join('.'); - this.opcode('pushId', 'BlockParam', blockParamIndex, blockParamChild); - } else { - value = val.original || value; - if (value.replace) { - value = value.replace(/^this(?:\.|$)/, '').replace(/^\.\//, '').replace(/^\.$/, ''); - } - - this.opcode('pushId', val.type, value); - } - } - this.accept(val); - } - }, - - setupFullMustacheParams: function setupFullMustacheParams(sexpr, program, inverse, omitEmpty) { - var params = sexpr.params; - this.pushParams(params); - - this.opcode('pushProgram', program); - this.opcode('pushProgram', inverse); - - if (sexpr.hash) { - this.accept(sexpr.hash); - } else { - this.opcode('emptyHash', omitEmpty); - } - - return params; - }, - - blockParamIndex: function blockParamIndex(name) { - for (var depth = 0, len = this.options.blockParams.length; depth < len; depth++) { - var blockParams = this.options.blockParams[depth], - param = blockParams && _utils.indexOf(blockParams, name); - if (blockParams && param >= 0) { - return [depth, param]; - } - } - } - }; - - function precompile(input, options, env) { - if (input == null || typeof input !== 'string' && input.type !== 'Program') { - throw new _exception2['default']('You must pass a string or Handlebars AST to Handlebars.precompile. You passed ' + input); - } - - options = options || {}; - if (!('data' in options)) { - options.data = true; - } - if (options.compat) { - options.useDepths = true; - } - - var ast = env.parse(input, options), - environment = new env.Compiler().compile(ast, options); - return new env.JavaScriptCompiler().compile(environment, options); - } - - function compile(input, options, env) { - if (options === undefined) options = {}; - - if (input == null || typeof input !== 'string' && input.type !== 'Program') { - throw new _exception2['default']('You must pass a string or Handlebars AST to Handlebars.compile. You passed ' + input); - } - - options = _utils.extend({}, options); - if (!('data' in options)) { - options.data = true; - } - if (options.compat) { - options.useDepths = true; - } - - var compiled = undefined; - - function compileInput() { - var ast = env.parse(input, options), - environment = new env.Compiler().compile(ast, options), - templateSpec = new env.JavaScriptCompiler().compile(environment, options, undefined, true); - return env.template(templateSpec); - } - - // Template is only compiled on first use and cached after that point. - function ret(context, execOptions) { - if (!compiled) { - compiled = compileInput(); - } - return compiled.call(this, context, execOptions); - } - ret._setup = function (setupOptions) { - if (!compiled) { - compiled = compileInput(); - } - return compiled._setup(setupOptions); - }; - ret._child = function (i, data, blockParams, depths) { - if (!compiled) { - compiled = compileInput(); - } - return compiled._child(i, data, blockParams, depths); - }; - return ret; - } - - function argEquals(a, b) { - if (a === b) { - return true; - } - - if (_utils.isArray(a) && _utils.isArray(b) && a.length === b.length) { - for (var i = 0; i < a.length; i++) { - if (!argEquals(a[i], b[i])) { - return false; - } - } - return true; - } - } - - function transformLiteralToPath(sexpr) { - if (!sexpr.path.parts) { - var literal = sexpr.path; - // Casting to string here to make false and 0 literal values play nicely with the rest - // of the system. - sexpr.path = { - type: 'PathExpression', - data: false, - depth: 0, - parts: [literal.original + ''], - original: literal.original + '', - loc: literal.loc - }; - } - } - -/***/ }), -/* 52 */ -/***/ (function(module, exports, __webpack_require__) { - - 'use strict'; - - var _Object$keys = __webpack_require__(13)['default']; - - var _interopRequireDefault = __webpack_require__(1)['default']; - - exports.__esModule = true; - - var _base = __webpack_require__(4); - - var _exception = __webpack_require__(6); - - var _exception2 = _interopRequireDefault(_exception); - - var _utils = __webpack_require__(5); - - var _codeGen = __webpack_require__(53); - - var _codeGen2 = _interopRequireDefault(_codeGen); - - function Literal(value) { - this.value = value; - } - - function JavaScriptCompiler() {} - - JavaScriptCompiler.prototype = { - // PUBLIC API: You can override these methods in a subclass to provide - // alternative compiled forms for name lookup and buffering semantics - nameLookup: function nameLookup(parent, name /*, type */) { - return this.internalNameLookup(parent, name); - }, - depthedLookup: function depthedLookup(name) { - return [this.aliasable('container.lookup'), '(depths, "', name, '")']; - }, - - compilerInfo: function compilerInfo() { - var revision = _base.COMPILER_REVISION, - versions = _base.REVISION_CHANGES[revision]; - return [revision, versions]; - }, - - appendToBuffer: function appendToBuffer(source, location, explicit) { - // Force a source as this simplifies the merge logic. - if (!_utils.isArray(source)) { - source = [source]; - } - source = this.source.wrap(source, location); - - if (this.environment.isSimple) { - return ['return ', source, ';']; - } else if (explicit) { - // This is a case where the buffer operation occurs as a child of another - // construct, generally braces. We have to explicitly output these buffer - // operations to ensure that the emitted code goes in the correct location. - return ['buffer += ', source, ';']; - } else { - source.appendToBuffer = true; - return source; - } - }, - - initializeBuffer: function initializeBuffer() { - return this.quotedString(''); - }, - // END PUBLIC API - internalNameLookup: function internalNameLookup(parent, name) { - this.lookupPropertyFunctionIsUsed = true; - return ['lookupProperty(', parent, ',', JSON.stringify(name), ')']; - }, - - lookupPropertyFunctionIsUsed: false, - - compile: function compile(environment, options, context, asObject) { - this.environment = environment; - this.options = options; - this.stringParams = this.options.stringParams; - this.trackIds = this.options.trackIds; - this.precompile = !asObject; - - this.name = this.environment.name; - this.isChild = !!context; - this.context = context || { - decorators: [], - programs: [], - environments: [] - }; - - this.preamble(); - - this.stackSlot = 0; - this.stackVars = []; - this.aliases = {}; - this.registers = { list: [] }; - this.hashes = []; - this.compileStack = []; - this.inlineStack = []; - this.blockParams = []; - - this.compileChildren(environment, options); - - this.useDepths = this.useDepths || environment.useDepths || environment.useDecorators || this.options.compat; - this.useBlockParams = this.useBlockParams || environment.useBlockParams; - - var opcodes = environment.opcodes, - opcode = undefined, - firstLoc = undefined, - i = undefined, - l = undefined; - - for (i = 0, l = opcodes.length; i < l; i++) { - opcode = opcodes[i]; - - this.source.currentLocation = opcode.loc; - firstLoc = firstLoc || opcode.loc; - this[opcode.opcode].apply(this, opcode.args); - } - - // Flush any trailing content that might be pending. - this.source.currentLocation = firstLoc; - this.pushSource(''); - - /* istanbul ignore next */ - if (this.stackSlot || this.inlineStack.length || this.compileStack.length) { - throw new _exception2['default']('Compile completed with content left on stack'); - } - - if (!this.decorators.isEmpty()) { - this.useDecorators = true; - - this.decorators.prepend(['var decorators = container.decorators, ', this.lookupPropertyFunctionVarDeclaration(), ';\n']); - this.decorators.push('return fn;'); - - if (asObject) { - this.decorators = Function.apply(this, ['fn', 'props', 'container', 'depth0', 'data', 'blockParams', 'depths', this.decorators.merge()]); - } else { - this.decorators.prepend('function(fn, props, container, depth0, data, blockParams, depths) {\n'); - this.decorators.push('}\n'); - this.decorators = this.decorators.merge(); - } - } else { - this.decorators = undefined; - } - - var fn = this.createFunctionContext(asObject); - if (!this.isChild) { - var ret = { - compiler: this.compilerInfo(), - main: fn - }; - - if (this.decorators) { - ret.main_d = this.decorators; // eslint-disable-line camelcase - ret.useDecorators = true; - } - - var _context = this.context; - var programs = _context.programs; - var decorators = _context.decorators; - - for (i = 0, l = programs.length; i < l; i++) { - if (programs[i]) { - ret[i] = programs[i]; - if (decorators[i]) { - ret[i + '_d'] = decorators[i]; - ret.useDecorators = true; - } - } - } - - if (this.environment.usePartial) { - ret.usePartial = true; - } - if (this.options.data) { - ret.useData = true; - } - if (this.useDepths) { - ret.useDepths = true; - } - if (this.useBlockParams) { - ret.useBlockParams = true; - } - if (this.options.compat) { - ret.compat = true; - } - - if (!asObject) { - ret.compiler = JSON.stringify(ret.compiler); - - this.source.currentLocation = { start: { line: 1, column: 0 } }; - ret = this.objectLiteral(ret); - - if (options.srcName) { - ret = ret.toStringWithSourceMap({ file: options.destName }); - ret.map = ret.map && ret.map.toString(); - } else { - ret = ret.toString(); - } - } else { - ret.compilerOptions = this.options; - } - - return ret; - } else { - return fn; - } - }, - - preamble: function preamble() { - // track the last context pushed into place to allow skipping the - // getContext opcode when it would be a noop - this.lastContext = 0; - this.source = new _codeGen2['default'](this.options.srcName); - this.decorators = new _codeGen2['default'](this.options.srcName); - }, - - createFunctionContext: function createFunctionContext(asObject) { - // istanbul ignore next - - var _this = this; - - var varDeclarations = ''; - - var locals = this.stackVars.concat(this.registers.list); - if (locals.length > 0) { - varDeclarations += ', ' + locals.join(', '); - } - - // Generate minimizer alias mappings - // - // When using true SourceNodes, this will update all references to the given alias - // as the source nodes are reused in situ. For the non-source node compilation mode, - // aliases will not be used, but this case is already being run on the client and - // we aren't concern about minimizing the template size. - var aliasCount = 0; - _Object$keys(this.aliases).forEach(function (alias) { - var node = _this.aliases[alias]; - if (node.children && node.referenceCount > 1) { - varDeclarations += ', alias' + ++aliasCount + '=' + alias; - node.children[0] = 'alias' + aliasCount; - } - }); - - if (this.lookupPropertyFunctionIsUsed) { - varDeclarations += ', ' + this.lookupPropertyFunctionVarDeclaration(); - } - - var params = ['container', 'depth0', 'helpers', 'partials', 'data']; - - if (this.useBlockParams || this.useDepths) { - params.push('blockParams'); - } - if (this.useDepths) { - params.push('depths'); - } - - // Perform a second pass over the output to merge content when possible - var source = this.mergeSource(varDeclarations); - - if (asObject) { - params.push(source); - - return Function.apply(this, params); - } else { - return this.source.wrap(['function(', params.join(','), ') {\n ', source, '}']); - } - }, - mergeSource: function mergeSource(varDeclarations) { - var isSimple = this.environment.isSimple, - appendOnly = !this.forceBuffer, - appendFirst = undefined, - sourceSeen = undefined, - bufferStart = undefined, - bufferEnd = undefined; - this.source.each(function (line) { - if (line.appendToBuffer) { - if (bufferStart) { - line.prepend(' + '); - } else { - bufferStart = line; - } - bufferEnd = line; - } else { - if (bufferStart) { - if (!sourceSeen) { - appendFirst = true; - } else { - bufferStart.prepend('buffer += '); - } - bufferEnd.add(';'); - bufferStart = bufferEnd = undefined; - } - - sourceSeen = true; - if (!isSimple) { - appendOnly = false; - } - } - }); - - if (appendOnly) { - if (bufferStart) { - bufferStart.prepend('return '); - bufferEnd.add(';'); - } else if (!sourceSeen) { - this.source.push('return "";'); - } - } else { - varDeclarations += ', buffer = ' + (appendFirst ? '' : this.initializeBuffer()); - - if (bufferStart) { - bufferStart.prepend('return buffer + '); - bufferEnd.add(';'); - } else { - this.source.push('return buffer;'); - } - } - - if (varDeclarations) { - this.source.prepend('var ' + varDeclarations.substring(2) + (appendFirst ? '' : ';\n')); - } - - return this.source.merge(); - }, - - lookupPropertyFunctionVarDeclaration: function lookupPropertyFunctionVarDeclaration() { - return '\n lookupProperty = container.lookupProperty || function(parent, propertyName) {\n if (Object.prototype.hasOwnProperty.call(parent, propertyName)) {\n return parent[propertyName];\n }\n return undefined\n }\n '.trim(); - }, - - // [blockValue] - // - // On stack, before: hash, inverse, program, value - // On stack, after: return value of blockHelperMissing - // - // The purpose of this opcode is to take a block of the form - // `{{#this.foo}}...{{/this.foo}}`, resolve the value of `foo`, and - // replace it on the stack with the result of properly - // invoking blockHelperMissing. - blockValue: function blockValue(name) { - var blockHelperMissing = this.aliasable('container.hooks.blockHelperMissing'), - params = [this.contextName(0)]; - this.setupHelperArgs(name, 0, params); - - var blockName = this.popStack(); - params.splice(1, 0, blockName); - - this.push(this.source.functionCall(blockHelperMissing, 'call', params)); - }, - - // [ambiguousBlockValue] - // - // On stack, before: hash, inverse, program, value - // Compiler value, before: lastHelper=value of last found helper, if any - // On stack, after, if no lastHelper: same as [blockValue] - // On stack, after, if lastHelper: value - ambiguousBlockValue: function ambiguousBlockValue() { - // We're being a bit cheeky and reusing the options value from the prior exec - var blockHelperMissing = this.aliasable('container.hooks.blockHelperMissing'), - params = [this.contextName(0)]; - this.setupHelperArgs('', 0, params, true); - - this.flushInline(); - - var current = this.topStack(); - params.splice(1, 0, current); - - this.pushSource(['if (!', this.lastHelper, ') { ', current, ' = ', this.source.functionCall(blockHelperMissing, 'call', params), '}']); - }, - - // [appendContent] - // - // On stack, before: ... - // On stack, after: ... - // - // Appends the string value of `content` to the current buffer - appendContent: function appendContent(content) { - if (this.pendingContent) { - content = this.pendingContent + content; - } else { - this.pendingLocation = this.source.currentLocation; - } - - this.pendingContent = content; - }, - - // [append] - // - // On stack, before: value, ... - // On stack, after: ... - // - // Coerces `value` to a String and appends it to the current buffer. - // - // If `value` is truthy, or 0, it is coerced into a string and appended - // Otherwise, the empty string is appended - append: function append() { - if (this.isInline()) { - this.replaceStack(function (current) { - return [' != null ? ', current, ' : ""']; - }); - - this.pushSource(this.appendToBuffer(this.popStack())); - } else { - var local = this.popStack(); - this.pushSource(['if (', local, ' != null) { ', this.appendToBuffer(local, undefined, true), ' }']); - if (this.environment.isSimple) { - this.pushSource(['else { ', this.appendToBuffer("''", undefined, true), ' }']); - } - } - }, - - // [appendEscaped] - // - // On stack, before: value, ... - // On stack, after: ... - // - // Escape `value` and append it to the buffer - appendEscaped: function appendEscaped() { - this.pushSource(this.appendToBuffer([this.aliasable('container.escapeExpression'), '(', this.popStack(), ')'])); - }, - - // [getContext] - // - // On stack, before: ... - // On stack, after: ... - // Compiler value, after: lastContext=depth - // - // Set the value of the `lastContext` compiler value to the depth - getContext: function getContext(depth) { - this.lastContext = depth; - }, - - // [pushContext] - // - // On stack, before: ... - // On stack, after: currentContext, ... - // - // Pushes the value of the current context onto the stack. - pushContext: function pushContext() { - this.pushStackLiteral(this.contextName(this.lastContext)); - }, - - // [lookupOnContext] - // - // On stack, before: ... - // On stack, after: currentContext[name], ... - // - // Looks up the value of `name` on the current context and pushes - // it onto the stack. - lookupOnContext: function lookupOnContext(parts, falsy, strict, scoped) { - var i = 0; - - if (!scoped && this.options.compat && !this.lastContext) { - // The depthed query is expected to handle the undefined logic for the root level that - // is implemented below, so we evaluate that directly in compat mode - this.push(this.depthedLookup(parts[i++])); - } else { - this.pushContext(); - } - - this.resolvePath('context', parts, i, falsy, strict); - }, - - // [lookupBlockParam] - // - // On stack, before: ... - // On stack, after: blockParam[name], ... - // - // Looks up the value of `parts` on the given block param and pushes - // it onto the stack. - lookupBlockParam: function lookupBlockParam(blockParamId, parts) { - this.useBlockParams = true; - - this.push(['blockParams[', blockParamId[0], '][', blockParamId[1], ']']); - this.resolvePath('context', parts, 1); - }, - - // [lookupData] - // - // On stack, before: ... - // On stack, after: data, ... - // - // Push the data lookup operator - lookupData: function lookupData(depth, parts, strict) { - if (!depth) { - this.pushStackLiteral('data'); - } else { - this.pushStackLiteral('container.data(data, ' + depth + ')'); - } - - this.resolvePath('data', parts, 0, true, strict); - }, - - resolvePath: function resolvePath(type, parts, i, falsy, strict) { - // istanbul ignore next - - var _this2 = this; - - if (this.options.strict || this.options.assumeObjects) { - this.push(strictLookup(this.options.strict && strict, this, parts, type)); - return; - } - - var len = parts.length; - for (; i < len; i++) { - /* eslint-disable no-loop-func */ - this.replaceStack(function (current) { - var lookup = _this2.nameLookup(current, parts[i], type); - // We want to ensure that zero and false are handled properly if the context (falsy flag) - // needs to have the special handling for these values. - if (!falsy) { - return [' != null ? ', lookup, ' : ', current]; - } else { - // Otherwise we can use generic falsy handling - return [' && ', lookup]; - } - }); - /* eslint-enable no-loop-func */ - } - }, - - // [resolvePossibleLambda] - // - // On stack, before: value, ... - // On stack, after: resolved value, ... - // - // If the `value` is a lambda, replace it on the stack by - // the return value of the lambda - resolvePossibleLambda: function resolvePossibleLambda() { - this.push([this.aliasable('container.lambda'), '(', this.popStack(), ', ', this.contextName(0), ')']); - }, - - // [pushStringParam] - // - // On stack, before: ... - // On stack, after: string, currentContext, ... - // - // This opcode is designed for use in string mode, which - // provides the string value of a parameter along with its - // depth rather than resolving it immediately. - pushStringParam: function pushStringParam(string, type) { - this.pushContext(); - this.pushString(type); - - // If it's a subexpression, the string result - // will be pushed after this opcode. - if (type !== 'SubExpression') { - if (typeof string === 'string') { - this.pushString(string); - } else { - this.pushStackLiteral(string); - } - } - }, - - emptyHash: function emptyHash(omitEmpty) { - if (this.trackIds) { - this.push('{}'); // hashIds - } - if (this.stringParams) { - this.push('{}'); // hashContexts - this.push('{}'); // hashTypes - } - this.pushStackLiteral(omitEmpty ? 'undefined' : '{}'); - }, - pushHash: function pushHash() { - if (this.hash) { - this.hashes.push(this.hash); - } - this.hash = { values: {}, types: [], contexts: [], ids: [] }; - }, - popHash: function popHash() { - var hash = this.hash; - this.hash = this.hashes.pop(); - - if (this.trackIds) { - this.push(this.objectLiteral(hash.ids)); - } - if (this.stringParams) { - this.push(this.objectLiteral(hash.contexts)); - this.push(this.objectLiteral(hash.types)); - } - - this.push(this.objectLiteral(hash.values)); - }, - - // [pushString] - // - // On stack, before: ... - // On stack, after: quotedString(string), ... - // - // Push a quoted version of `string` onto the stack - pushString: function pushString(string) { - this.pushStackLiteral(this.quotedString(string)); - }, - - // [pushLiteral] - // - // On stack, before: ... - // On stack, after: value, ... - // - // Pushes a value onto the stack. This operation prevents - // the compiler from creating a temporary variable to hold - // it. - pushLiteral: function pushLiteral(value) { - this.pushStackLiteral(value); - }, - - // [pushProgram] - // - // On stack, before: ... - // On stack, after: program(guid), ... - // - // Push a program expression onto the stack. This takes - // a compile-time guid and converts it into a runtime-accessible - // expression. - pushProgram: function pushProgram(guid) { - if (guid != null) { - this.pushStackLiteral(this.programExpression(guid)); - } else { - this.pushStackLiteral(null); - } - }, - - // [registerDecorator] - // - // On stack, before: hash, program, params..., ... - // On stack, after: ... - // - // Pops off the decorator's parameters, invokes the decorator, - // and inserts the decorator into the decorators list. - registerDecorator: function registerDecorator(paramSize, name) { - var foundDecorator = this.nameLookup('decorators', name, 'decorator'), - options = this.setupHelperArgs(name, paramSize); - - this.decorators.push(['fn = ', this.decorators.functionCall(foundDecorator, '', ['fn', 'props', 'container', options]), ' || fn;']); - }, - - // [invokeHelper] - // - // On stack, before: hash, inverse, program, params..., ... - // On stack, after: result of helper invocation - // - // Pops off the helper's parameters, invokes the helper, - // and pushes the helper's return value onto the stack. - // - // If the helper is not found, `helperMissing` is called. - invokeHelper: function invokeHelper(paramSize, name, isSimple) { - var nonHelper = this.popStack(), - helper = this.setupHelper(paramSize, name); - - var possibleFunctionCalls = []; - - if (isSimple) { - // direct call to helper - possibleFunctionCalls.push(helper.name); - } - // call a function from the input object - possibleFunctionCalls.push(nonHelper); - if (!this.options.strict) { - possibleFunctionCalls.push(this.aliasable('container.hooks.helperMissing')); - } - - var functionLookupCode = ['(', this.itemsSeparatedBy(possibleFunctionCalls, '||'), ')']; - var functionCall = this.source.functionCall(functionLookupCode, 'call', helper.callParams); - this.push(functionCall); - }, - - itemsSeparatedBy: function itemsSeparatedBy(items, separator) { - var result = []; - result.push(items[0]); - for (var i = 1; i < items.length; i++) { - result.push(separator, items[i]); - } - return result; - }, - // [invokeKnownHelper] - // - // On stack, before: hash, inverse, program, params..., ... - // On stack, after: result of helper invocation - // - // This operation is used when the helper is known to exist, - // so a `helperMissing` fallback is not required. - invokeKnownHelper: function invokeKnownHelper(paramSize, name) { - var helper = this.setupHelper(paramSize, name); - this.push(this.source.functionCall(helper.name, 'call', helper.callParams)); - }, - - // [invokeAmbiguous] - // - // On stack, before: hash, inverse, program, params..., ... - // On stack, after: result of disambiguation - // - // This operation is used when an expression like `{{foo}}` - // is provided, but we don't know at compile-time whether it - // is a helper or a path. - // - // This operation emits more code than the other options, - // and can be avoided by passing the `knownHelpers` and - // `knownHelpersOnly` flags at compile-time. - invokeAmbiguous: function invokeAmbiguous(name, helperCall) { - this.useRegister('helper'); - - var nonHelper = this.popStack(); - - this.emptyHash(); - var helper = this.setupHelper(0, name, helperCall); - - var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper'); - - var lookup = ['(', '(helper = ', helperName, ' || ', nonHelper, ')']; - if (!this.options.strict) { - lookup[0] = '(helper = '; - lookup.push(' != null ? helper : ', this.aliasable('container.hooks.helperMissing')); - } - - this.push(['(', lookup, helper.paramsInit ? ['),(', helper.paramsInit] : [], '),', '(typeof helper === ', this.aliasable('"function"'), ' ? ', this.source.functionCall('helper', 'call', helper.callParams), ' : helper))']); - }, - - // [invokePartial] - // - // On stack, before: context, ... - // On stack after: result of partial invocation - // - // This operation pops off a context, invokes a partial with that context, - // and pushes the result of the invocation back. - invokePartial: function invokePartial(isDynamic, name, indent) { - var params = [], - options = this.setupParams(name, 1, params); - - if (isDynamic) { - name = this.popStack(); - delete options.name; - } - - if (indent) { - options.indent = JSON.stringify(indent); - } - options.helpers = 'helpers'; - options.partials = 'partials'; - options.decorators = 'container.decorators'; - - if (!isDynamic) { - params.unshift(this.nameLookup('partials', name, 'partial')); - } else { - params.unshift(name); - } - - if (this.options.compat) { - options.depths = 'depths'; - } - options = this.objectLiteral(options); - params.push(options); - - this.push(this.source.functionCall('container.invokePartial', '', params)); - }, - - // [assignToHash] - // - // On stack, before: value, ..., hash, ... - // On stack, after: ..., hash, ... - // - // Pops a value off the stack and assigns it to the current hash - assignToHash: function assignToHash(key) { - var value = this.popStack(), - context = undefined, - type = undefined, - id = undefined; - - if (this.trackIds) { - id = this.popStack(); - } - if (this.stringParams) { - type = this.popStack(); - context = this.popStack(); - } - - var hash = this.hash; - if (context) { - hash.contexts[key] = context; - } - if (type) { - hash.types[key] = type; - } - if (id) { - hash.ids[key] = id; - } - hash.values[key] = value; - }, - - pushId: function pushId(type, name, child) { - if (type === 'BlockParam') { - this.pushStackLiteral('blockParams[' + name[0] + '].path[' + name[1] + ']' + (child ? ' + ' + JSON.stringify('.' + child) : '')); - } else if (type === 'PathExpression') { - this.pushString(name); - } else if (type === 'SubExpression') { - this.pushStackLiteral('true'); - } else { - this.pushStackLiteral('null'); - } - }, - - // HELPERS - - compiler: JavaScriptCompiler, - - compileChildren: function compileChildren(environment, options) { - var children = environment.children, - child = undefined, - compiler = undefined; - - for (var i = 0, l = children.length; i < l; i++) { - child = children[i]; - compiler = new this.compiler(); // eslint-disable-line new-cap - - var existing = this.matchExistingProgram(child); - - if (existing == null) { - this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children - var index = this.context.programs.length; - child.index = index; - child.name = 'program' + index; - this.context.programs[index] = compiler.compile(child, options, this.context, !this.precompile); - this.context.decorators[index] = compiler.decorators; - this.context.environments[index] = child; - - this.useDepths = this.useDepths || compiler.useDepths; - this.useBlockParams = this.useBlockParams || compiler.useBlockParams; - child.useDepths = this.useDepths; - child.useBlockParams = this.useBlockParams; - } else { - child.index = existing.index; - child.name = 'program' + existing.index; - - this.useDepths = this.useDepths || existing.useDepths; - this.useBlockParams = this.useBlockParams || existing.useBlockParams; - } - } - }, - matchExistingProgram: function matchExistingProgram(child) { - for (var i = 0, len = this.context.environments.length; i < len; i++) { - var environment = this.context.environments[i]; - if (environment && environment.equals(child)) { - return environment; - } - } - }, - - programExpression: function programExpression(guid) { - var child = this.environment.children[guid], - programParams = [child.index, 'data', child.blockParams]; - - if (this.useBlockParams || this.useDepths) { - programParams.push('blockParams'); - } - if (this.useDepths) { - programParams.push('depths'); - } - - return 'container.program(' + programParams.join(', ') + ')'; - }, - - useRegister: function useRegister(name) { - if (!this.registers[name]) { - this.registers[name] = true; - this.registers.list.push(name); - } - }, - - push: function push(expr) { - if (!(expr instanceof Literal)) { - expr = this.source.wrap(expr); - } - - this.inlineStack.push(expr); - return expr; - }, - - pushStackLiteral: function pushStackLiteral(item) { - this.push(new Literal(item)); - }, - - pushSource: function pushSource(source) { - if (this.pendingContent) { - this.source.push(this.appendToBuffer(this.source.quotedString(this.pendingContent), this.pendingLocation)); - this.pendingContent = undefined; - } - - if (source) { - this.source.push(source); - } - }, - - replaceStack: function replaceStack(callback) { - var prefix = ['('], - stack = undefined, - createdStack = undefined, - usedLiteral = undefined; - - /* istanbul ignore next */ - if (!this.isInline()) { - throw new _exception2['default']('replaceStack on non-inline'); - } - - // We want to merge the inline statement into the replacement statement via ',' - var top = this.popStack(true); - - if (top instanceof Literal) { - // Literals do not need to be inlined - stack = [top.value]; - prefix = ['(', stack]; - usedLiteral = true; - } else { - // Get or create the current stack name for use by the inline - createdStack = true; - var _name = this.incrStack(); - - prefix = ['((', this.push(_name), ' = ', top, ')']; - stack = this.topStack(); - } - - var item = callback.call(this, stack); - - if (!usedLiteral) { - this.popStack(); - } - if (createdStack) { - this.stackSlot--; - } - this.push(prefix.concat(item, ')')); - }, - - incrStack: function incrStack() { - this.stackSlot++; - if (this.stackSlot > this.stackVars.length) { - this.stackVars.push('stack' + this.stackSlot); - } - return this.topStackName(); - }, - topStackName: function topStackName() { - return 'stack' + this.stackSlot; - }, - flushInline: function flushInline() { - var inlineStack = this.inlineStack; - this.inlineStack = []; - for (var i = 0, len = inlineStack.length; i < len; i++) { - var entry = inlineStack[i]; - /* istanbul ignore if */ - if (entry instanceof Literal) { - this.compileStack.push(entry); - } else { - var stack = this.incrStack(); - this.pushSource([stack, ' = ', entry, ';']); - this.compileStack.push(stack); - } - } - }, - isInline: function isInline() { - return this.inlineStack.length; - }, - - popStack: function popStack(wrapped) { - var inline = this.isInline(), - item = (inline ? this.inlineStack : this.compileStack).pop(); - - if (!wrapped && item instanceof Literal) { - return item.value; - } else { - if (!inline) { - /* istanbul ignore next */ - if (!this.stackSlot) { - throw new _exception2['default']('Invalid stack pop'); - } - this.stackSlot--; - } - return item; - } - }, - - topStack: function topStack() { - var stack = this.isInline() ? this.inlineStack : this.compileStack, - item = stack[stack.length - 1]; - - /* istanbul ignore if */ - if (item instanceof Literal) { - return item.value; - } else { - return item; - } - }, - - contextName: function contextName(context) { - if (this.useDepths && context) { - return 'depths[' + context + ']'; - } else { - return 'depth' + context; - } - }, - - quotedString: function quotedString(str) { - return this.source.quotedString(str); - }, - - objectLiteral: function objectLiteral(obj) { - return this.source.objectLiteral(obj); - }, - - aliasable: function aliasable(name) { - var ret = this.aliases[name]; - if (ret) { - ret.referenceCount++; - return ret; - } - - ret = this.aliases[name] = this.source.wrap(name); - ret.aliasable = true; - ret.referenceCount = 1; - - return ret; - }, - - setupHelper: function setupHelper(paramSize, name, blockHelper) { - var params = [], - paramsInit = this.setupHelperArgs(name, paramSize, params, blockHelper); - var foundHelper = this.nameLookup('helpers', name, 'helper'), - callContext = this.aliasable(this.contextName(0) + ' != null ? ' + this.contextName(0) + ' : (container.nullContext || {})'); - - return { - params: params, - paramsInit: paramsInit, - name: foundHelper, - callParams: [callContext].concat(params) - }; - }, - - setupParams: function setupParams(helper, paramSize, params) { - var options = {}, - contexts = [], - types = [], - ids = [], - objectArgs = !params, - param = undefined; - - if (objectArgs) { - params = []; - } - - options.name = this.quotedString(helper); - options.hash = this.popStack(); - - if (this.trackIds) { - options.hashIds = this.popStack(); - } - if (this.stringParams) { - options.hashTypes = this.popStack(); - options.hashContexts = this.popStack(); - } - - var inverse = this.popStack(), - program = this.popStack(); - - // Avoid setting fn and inverse if neither are set. This allows - // helpers to do a check for `if (options.fn)` - if (program || inverse) { - options.fn = program || 'container.noop'; - options.inverse = inverse || 'container.noop'; - } - - // The parameters go on to the stack in order (making sure that they are evaluated in order) - // so we need to pop them off the stack in reverse order - var i = paramSize; - while (i--) { - param = this.popStack(); - params[i] = param; - - if (this.trackIds) { - ids[i] = this.popStack(); - } - if (this.stringParams) { - types[i] = this.popStack(); - contexts[i] = this.popStack(); - } - } - - if (objectArgs) { - options.args = this.source.generateArray(params); - } - - if (this.trackIds) { - options.ids = this.source.generateArray(ids); - } - if (this.stringParams) { - options.types = this.source.generateArray(types); - options.contexts = this.source.generateArray(contexts); - } - - if (this.options.data) { - options.data = 'data'; - } - if (this.useBlockParams) { - options.blockParams = 'blockParams'; - } - return options; - }, - - setupHelperArgs: function setupHelperArgs(helper, paramSize, params, useRegister) { - var options = this.setupParams(helper, paramSize, params); - options.loc = JSON.stringify(this.source.currentLocation); - options = this.objectLiteral(options); - if (useRegister) { - this.useRegister('options'); - params.push('options'); - return ['options=', options]; - } else if (params) { - params.push(options); - return ''; - } else { - return options; - } - } - }; - - (function () { - var reservedWords = ('break else new var' + ' case finally return void' + ' catch for switch while' + ' continue function this with' + ' default if throw' + ' delete in try' + ' do instanceof typeof' + ' abstract enum int short' + ' boolean export interface static' + ' byte extends long super' + ' char final native synchronized' + ' class float package throws' + ' const goto private transient' + ' debugger implements protected volatile' + ' double import public let yield await' + ' null true false').split(' '); - - var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {}; - - for (var i = 0, l = reservedWords.length; i < l; i++) { - compilerWords[reservedWords[i]] = true; - } - })(); - - /** - * @deprecated May be removed in the next major version - */ - JavaScriptCompiler.isValidJavaScriptVariableName = function (name) { - return !JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(name); - }; - - function strictLookup(requireTerminal, compiler, parts, type) { - var stack = compiler.popStack(), - i = 0, - len = parts.length; - if (requireTerminal) { - len--; - } - - for (; i < len; i++) { - stack = compiler.nameLookup(stack, parts[i], type); - } - - if (requireTerminal) { - return [compiler.aliasable('container.strict'), '(', stack, ', ', compiler.quotedString(parts[i]), ', ', JSON.stringify(compiler.source.currentLocation), ' )']; - } else { - return stack; - } - } - - exports['default'] = JavaScriptCompiler; - module.exports = exports['default']; - -/***/ }), -/* 53 */ -/***/ (function(module, exports, __webpack_require__) { - - /* global define */ - 'use strict'; - - var _Object$keys = __webpack_require__(13)['default']; - - exports.__esModule = true; - - var _utils = __webpack_require__(5); - - var SourceNode = undefined; - - try { - /* istanbul ignore next */ - if (false) { - // We don't support this in AMD environments. For these environments, we asusme that - // they are running on the browser and thus have no need for the source-map library. - var SourceMap = require('source-map'); - SourceNode = SourceMap.SourceNode; - } - } catch (err) {} - /* NOP */ - - /* istanbul ignore if: tested but not covered in istanbul due to dist build */ - if (!SourceNode) { - SourceNode = function (line, column, srcFile, chunks) { - this.src = ''; - if (chunks) { - this.add(chunks); - } - }; - /* istanbul ignore next */ - SourceNode.prototype = { - add: function add(chunks) { - if (_utils.isArray(chunks)) { - chunks = chunks.join(''); - } - this.src += chunks; - }, - prepend: function prepend(chunks) { - if (_utils.isArray(chunks)) { - chunks = chunks.join(''); - } - this.src = chunks + this.src; - }, - toStringWithSourceMap: function toStringWithSourceMap() { - return { code: this.toString() }; - }, - toString: function toString() { - return this.src; - } - }; - } - - function castChunk(chunk, codeGen, loc) { - if (_utils.isArray(chunk)) { - var ret = []; - - for (var i = 0, len = chunk.length; i < len; i++) { - ret.push(codeGen.wrap(chunk[i], loc)); - } - return ret; - } else if (typeof chunk === 'boolean' || typeof chunk === 'number') { - // Handle primitives that the SourceNode will throw up on - return chunk + ''; - } - return chunk; - } - - function CodeGen(srcFile) { - this.srcFile = srcFile; - this.source = []; - } - - CodeGen.prototype = { - isEmpty: function isEmpty() { - return !this.source.length; - }, - prepend: function prepend(source, loc) { - this.source.unshift(this.wrap(source, loc)); - }, - push: function push(source, loc) { - this.source.push(this.wrap(source, loc)); - }, - - merge: function merge() { - var source = this.empty(); - this.each(function (line) { - source.add([' ', line, '\n']); - }); - return source; - }, - - each: function each(iter) { - for (var i = 0, len = this.source.length; i < len; i++) { - iter(this.source[i]); - } - }, - - empty: function empty() { - var loc = this.currentLocation || { start: {} }; - return new SourceNode(loc.start.line, loc.start.column, this.srcFile); - }, - wrap: function wrap(chunk) { - var loc = arguments.length <= 1 || arguments[1] === undefined ? this.currentLocation || { start: {} } : arguments[1]; - - if (chunk instanceof SourceNode) { - return chunk; - } - - chunk = castChunk(chunk, this, loc); - - return new SourceNode(loc.start.line, loc.start.column, this.srcFile, chunk); - }, - - functionCall: function functionCall(fn, type, params) { - params = this.generateList(params); - return this.wrap([fn, type ? '.' + type + '(' : '(', params, ')']); - }, - - quotedString: function quotedString(str) { - return '"' + (str + '').replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n').replace(/\r/g, '\\r').replace(/\u2028/g, '\\u2028') // Per Ecma-262 7.3 + 7.8.4 - .replace(/\u2029/g, '\\u2029') + '"'; - }, - - objectLiteral: function objectLiteral(obj) { - // istanbul ignore next - - var _this = this; - - var pairs = []; - - _Object$keys(obj).forEach(function (key) { - var value = castChunk(obj[key], _this); - if (value !== 'undefined') { - pairs.push([_this.quotedString(key), ':', value]); - } - }); - - var ret = this.generateList(pairs); - ret.prepend('{'); - ret.add('}'); - return ret; - }, - - generateList: function generateList(entries) { - var ret = this.empty(); - - for (var i = 0, len = entries.length; i < len; i++) { - if (i) { - ret.add(','); - } - - ret.add(castChunk(entries[i], this)); - } - - return ret; - }, - - generateArray: function generateArray(entries) { - var ret = this.generateList(entries); - ret.prepend('['); - ret.add(']'); - - return ret; - } - }; - - exports['default'] = CodeGen; - module.exports = exports['default']; - -/***/ }) -/******/ ]) -}); -; \ No newline at end of file diff --git a/src/test/resources/libraries/htmx/htmx-1.9.11/test/lib/morphdom-umd.js b/src/test/resources/libraries/htmx/htmx-1.9.11/test/lib/morphdom-umd.js deleted file mode 100644 index 21fdc3a9a8c..00000000000 --- a/src/test/resources/libraries/htmx/htmx-1.9.11/test/lib/morphdom-umd.js +++ /dev/null @@ -1,763 +0,0 @@ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - (global = global || self, global.morphdom = factory()); -}(this, function () { 'use strict'; - - var DOCUMENT_FRAGMENT_NODE = 11; - - function morphAttrs(fromNode, toNode) { - var toNodeAttrs = toNode.attributes; - var attr; - var attrName; - var attrNamespaceURI; - var attrValue; - var fromValue; - - // document-fragments dont have attributes so lets not do anything - if (toNode.nodeType === DOCUMENT_FRAGMENT_NODE || fromNode.nodeType === DOCUMENT_FRAGMENT_NODE) { - return; - } - - // update attributes on original DOM element - for (var i = toNodeAttrs.length - 1; i >= 0; i--) { - attr = toNodeAttrs[i]; - attrName = attr.name; - attrNamespaceURI = attr.namespaceURI; - attrValue = attr.value; - - if (attrNamespaceURI) { - attrName = attr.localName || attrName; - fromValue = fromNode.getAttributeNS(attrNamespaceURI, attrName); - - if (fromValue !== attrValue) { - if (attr.prefix === 'xmlns'){ - attrName = attr.name; // It's not allowed to set an attribute with the XMLNS namespace without specifying the `xmlns` prefix - } - fromNode.setAttributeNS(attrNamespaceURI, attrName, attrValue); - } - } else { - fromValue = fromNode.getAttribute(attrName); - - if (fromValue !== attrValue) { - fromNode.setAttribute(attrName, attrValue); - } - } - } - - // Remove any extra attributes found on the original DOM element that - // weren't found on the target element. - var fromNodeAttrs = fromNode.attributes; - - for (var d = fromNodeAttrs.length - 1; d >= 0; d--) { - attr = fromNodeAttrs[d]; - attrName = attr.name; - attrNamespaceURI = attr.namespaceURI; - - if (attrNamespaceURI) { - attrName = attr.localName || attrName; - - if (!toNode.hasAttributeNS(attrNamespaceURI, attrName)) { - fromNode.removeAttributeNS(attrNamespaceURI, attrName); - } - } else { - if (!toNode.hasAttribute(attrName)) { - fromNode.removeAttribute(attrName); - } - } - } - } - - var range; // Create a range object for efficently rendering strings to elements. - var NS_XHTML = 'http://www.w3.org/1999/xhtml'; - - var doc = typeof document === 'undefined' ? undefined : document; - var HAS_TEMPLATE_SUPPORT = !!doc && 'content' in doc.createElement('template'); - var HAS_RANGE_SUPPORT = !!doc && doc.createRange && 'createContextualFragment' in doc.createRange(); - - function createFragmentFromTemplate(str) { - var template = doc.createElement('template'); - template.innerHTML = str; - return template.content.childNodes[0]; - } - - function createFragmentFromRange(str) { - if (!range) { - range = doc.createRange(); - range.selectNode(doc.body); - } - - var fragment = range.createContextualFragment(str); - return fragment.childNodes[0]; - } - - function createFragmentFromWrap(str) { - var fragment = doc.createElement('body'); - fragment.innerHTML = str; - return fragment.childNodes[0]; - } - - /** - * This is about the same - * var html = new DOMParser().parseFromString(str, 'text/html'); - * return html.body.firstChild; - * - * @method toElement - * @param {String} str - */ - function toElement(str) { - str = str.trim(); - if (HAS_TEMPLATE_SUPPORT) { - // avoid restrictions on content for things like `Hi` which - // createContextualFragment doesn't support - //