]> source.dussan.org Git - jquery.git/commitdiff
Build: Run GitHub Action browser tests on Playwright WebKit
authorMichał Gołębiowski-Owczarek <m.goleb@gmail.com>
Mon, 23 Jan 2023 22:49:44 +0000 (23:49 +0100)
committerGitHub <noreply@github.com>
Mon, 23 Jan 2023 22:49:44 +0000 (23:49 +0100)
So far, we've been running browser tests on GitHub Actions in Chrome
and Firefox. Regular Safari is not available in GitHub Actions but
Playwright WebKit comes close to a dev version of Safari.

With this change, our GitHub CI & local test runs will invoke tests on
all actively developed browser engines on all PRs.

Also, our GitHub Actions browser tests are now running on Node.js 18.

Detection of the Playwright WebKit browser in support unit tests is done
by checking if the `test_browser` query parameter is set to `"Playwright"`;
this is a `karma-webkit-launcher` feature. Detecting that browser via
user agent as we normally do is hard as the UA on Linux is very similar
to a real Safari one but it actually uses a newer version of the engine.

In addition, we now allow to pass custom browsers when one needs it;
e.g., to run the tests in all three engines on Linux/macOS, run:
```
grunt && BROWSERS=ChromeHeadless,FirefoxHeadless,WebkitHeadless grunt karma:main
```

Closes gh-5190

.github/workflows/node.js.yml
Gruntfile.js
package.json
test/unit/ajax.js
test/unit/css.js
test/unit/selector.js
test/unit/support.js

index 9600af2153afdf915b7d2451c5988bc4f0acca3e..56ca46bfc8747b6463b274abcf06546993cfccff 100644 (file)
@@ -16,32 +16,32 @@ jobs:
         NODE_VERSION: [10.x, 14.x, 16.x, 18.x, 19.x]
         NPM_SCRIPT: ["test:browserless"]
         include:
-          - NAME: "Browser tests: full build, Chrome & Firefox stable"
-            NODE_VERSION: "16.x"
+          - NAME: "Browser tests: full build, Chrome, Firefox & WebKit"
+            NODE_VERSION: "18.x"
             NPM_SCRIPT: "test:browser"
-            BROWSERS: "ChromeHeadless,FirefoxHeadless"
-          - NAME: "Browser tests: slim build, Chrome stable"
-            NODE_VERSION: "16.x"
+            BROWSERS: "ChromeHeadless,FirefoxHeadless,WebkitHeadless"
+          - NAME: "Browser tests: slim build, Chrome"
+            NODE_VERSION: "18.x"
             NPM_SCRIPT: "test:slim"
             BROWSERS: "ChromeHeadless"
-          - NAME: "Browser tests: no-deprecated build, Chrome stable"
-            NODE_VERSION: "16.x"
+          - NAME: "Browser tests: no-deprecated build, Chrome"
+            NODE_VERSION: "18.x"
             NPM_SCRIPT: "test:no-deprecated"
             BROWSERS: "ChromeHeadless"
-          - NAME: "Browser tests: selector-native build, Chrome stable"
-            NODE_VERSION: "16.x"
+          - NAME: "Browser tests: selector-native build, Chrome"
+            NODE_VERSION: "18.x"
             NPM_SCRIPT: "test:selector-native"
             BROWSERS: "ChromeHeadless"
-          - NAME: "Browser tests: ES modules build, Chrome stable"
-            NODE_VERSION: "16.x"
+          - NAME: "Browser tests: ES modules build, Chrome"
+            NODE_VERSION: "18.x"
             NPM_SCRIPT: "test:esmodules"
             BROWSERS: "ChromeHeadless"
-          - NAME: "Browser tests: AMD build, Chrome stable"
-            NODE_VERSION: "16.x"
+          - NAME: "Browser tests: AMD build, Chrome"
+            NODE_VERSION: "18.x"
             NPM_SCRIPT: "test:amd"
             BROWSERS: "ChromeHeadless"
           - NAME: "Browser tests: full build, Firefox ESR"
-            NODE_VERSION: "16.x"
+            NODE_VERSION: "18.x"
             NPM_SCRIPT: "test:browser"
             BROWSERS: "FirefoxHeadless"
     steps:
@@ -71,6 +71,10 @@ jobs:
       run: |
         npm install
 
+    - name: Install Playwright dependencies
+      run: npx playwright-webkit install-deps
+      if: "matrix.NPM_SCRIPT == 'test:browser'"
+
     - name: Run tests
       env:
         BROWSERS: ${{ matrix.BROWSERS }}
index 3a56cb4e49de700ea2ecc76006688fa75338bd38..f24e8a4485a2e3a9c9ae14eed7a67c935390102e 100644 (file)
@@ -2,8 +2,8 @@
 
 module.exports = function( grunt ) {
        function readOptionalJSON( filepath ) {
-               var stripJSONComments = require( "strip-json-comments" ),
-                       data = {};
+               const stripJSONComments = require( "strip-json-comments" );
+               let data = {};
                try {
                        data = JSON.parse( stripJSONComments(
                                fs.readFileSync( filepath, { encoding: "utf8" } )
@@ -12,19 +12,23 @@ module.exports = function( grunt ) {
                return data;
        }
 
-       // Support: Node.js <12
-       // Skip running tasks that dropped support for Node.js 10
+       const fs = require( "fs" );
+       const gzip = require( "gzip-js" );
+       const nodeV14OrNewer = !/^v1[0-3]\./.test( process.version );
+       const nodeV17OrNewer = !/^v1[0-6]\./.test( process.version );
+       const customBrowsers = process.env.BROWSERS && process.env.BROWSERS.split( "," );
+
+       // Support: Node.js <14
+       // Skip running tasks that dropped support for Node.js 10 or 12
        // in this Node version.
        function runIfNewNode( task ) {
-               return oldNode ? "print_old_node_message:" + task : task;
+               return nodeV14OrNewer ? task : "print_old_node_message:" + task;
        }
 
-       var fs = require( "fs" ),
-               gzip = require( "gzip-js" ),
-               oldNode = /^v10\./.test( process.version ),
-               nodeV17OrNewer = !/^v1[0246]\./.test( process.version ),
-               isCi = process.env.GITHUB_ACTION,
-               ciBrowsers = process.env.BROWSERS && process.env.BROWSERS.split( "," );
+       if ( nodeV14OrNewer ) {
+               const playwright = require( "playwright-webkit" );
+               process.env.WEBKIT_HEADLESS_BIN = playwright.webkit.executablePath();
+       }
 
        if ( !grunt.option( "filename" ) ) {
                grunt.option( "filename", "jquery.js" );
@@ -242,10 +246,11 @@ module.exports = function( grunt ) {
                                singleRun: true
                        },
                        main: {
-                               browsers: isCi && ciBrowsers || [ "ChromeHeadless", "FirefoxHeadless" ]
+                               browsers: customBrowsers ||
+                                       [ "ChromeHeadless", "FirefoxHeadless", "WebkitHeadless" ]
                        },
                        esmodules: {
-                               browsers: isCi && ciBrowsers || [ "ChromeHeadless" ],
+                               browsers: customBrowsers || [ "ChromeHeadless" ],
                                options: {
                                        client: {
                                                qunit: {
@@ -260,7 +265,7 @@ module.exports = function( grunt ) {
                                }
                        },
                        amd: {
-                               browsers: isCi && ciBrowsers || [ "ChromeHeadless" ],
+                               browsers: customBrowsers || [ "ChromeHeadless" ],
                                options: {
                                        client: {
                                                qunit: {
@@ -352,7 +357,7 @@ module.exports = function( grunt ) {
 
        // Load grunt tasks from NPM packages
        require( "load-grunt-tasks" )( grunt, {
-               pattern: oldNode ? [ "grunt-*", "!grunt-eslint" ] : [ "grunt-*" ]
+               pattern: nodeV14OrNewer ? [ "grunt-*" ] : [ "grunt-*", "!grunt-eslint" ]
        } );
 
        // Integrate jQuery specific tasks
index 3fee5c5eb2321a86091f9e9bbb70306b7eaa9211..3afa4e5f175e69a9c35aeccd2a9ffaade597c318 100644 (file)
@@ -23,7 +23,6 @@
     "url": "https://github.com/jquery/jquery/issues"
   },
   "license": "MIT",
-  "dependencies": {},
   "devDependencies": {
     "@babel/core": "7.10.5",
     "@babel/plugin-transform-for-of": "7.10.4",
     "gzip-js": "0.3.2",
     "husky": "4.2.5",
     "jsdom": "19.0.0",
-    "karma": "^6.3.17",
+    "karma": "6.4.1",
     "karma-browserstack-launcher": "1.6.0",
     "karma-chrome-launcher": "3.1.1",
     "karma-firefox-launcher": "2.1.2",
     "karma-ie-launcher": "1.0.0",
     "karma-jsdom-launcher": "12.0.0",
     "karma-qunit": "4.1.2",
+    "karma-webkit-launcher": "2.1.0",
     "load-grunt-tasks": "5.1.0",
     "native-promise-only": "0.8.1",
+    "playwright-webkit": "1.29.2",
     "promises-aplus-tests": "2.1.2",
     "q": "1.5.1",
     "qunit": "2.10.1",
index 18e36489dabcd0852e814171f4072e56db28f910..166d31de06532b4a74636648915c8c8f3a4c298c 100644 (file)
@@ -2270,7 +2270,7 @@ if ( typeof window.ArrayBuffer === "undefined" || typeof new XMLHttpRequest().re
        // beforeunload, unload, pagehide, and visibilitychange event handlers.
        // See https://bugs.chromium.org/p/chromium/issues/detail?id=952452
        // Safari 13 did similar changes. The below check will catch them both.
-       if ( !/safari/i.test( navigator.userAgent ) ) {
+       if ( !/webkit/i.test( navigator.userAgent ) ) {
                testIframe(
                        "trac-14379 - jQuery.ajax() on unload",
                        "ajax/onunload.html",
index a7a501df18f276b260938910ad92174465744912..e4a11175ffb06337b681525bf4d3690bdc3b5b57 100644 (file)
@@ -1757,7 +1757,7 @@ QUnit.testUnlessIE( "css(--customProperty)", function( assert ) {
        var div = jQuery( "<div>" ).appendTo( "#qunit-fixture" ),
                $elem = jQuery( "<div>" ).addClass( "test__customProperties" )
                        .appendTo( "#qunit-fixture" ),
-               webkitOrBlink = /\bsafari\b/i.test( navigator.userAgent ),
+               webkitOrBlink = /\webkit\b/i.test( navigator.userAgent ),
                expected = 20;
 
        if ( webkitOrBlink ) {
index d177ab9970f8997600fc3886a82f7c58b452a4ae..649b1e225b107472dcbbe7fcc281ea9c95b394e4 100644 (file)
@@ -1,7 +1,11 @@
 QUnit.module( "selector", {
        beforeEach: function() {
-               this.safari = /\bsafari\b/i.test( navigator.userAgent ) &&
-                       !/\b(?:headless)?chrome\b/i.test( navigator.userAgent );
+
+               // Playwright WebKit on macOS doesn't expose `Safari` in its user agent
+               // string; use the "AppleWebKit" token. This token is also present
+               // in the Chromium UA, but it is locked to an older version there.
+               // Modern WebKit (Safari 13+) locks it to `605.1.15`.
+               this.safari = /\bapplewebkit\/605\.1\.15\b/i.test( navigator.userAgent );
        },
        afterEach: moduleTeardown
 } );
index dc50700e89a90d2221b137f3299401516a1ad4d0..aa3386ef839b7a6b8cd3423d280803bee7ea904b 100644 (file)
@@ -70,6 +70,10 @@ testIframe(
                                cssSupportsSelector: false,
                                reliableTrDimensions: true
                        },
+                       webkit: {
+                               cssSupportsSelector: true,
+                               reliableTrDimensions: true
+                       },
                        firefox_102: {
                                cssSupportsSelector: false,
                                reliableTrDimensions: false
@@ -97,14 +101,26 @@ testIframe(
 
                // Catches Edge, Chrome on Android & Opera as well.
                expected = expectedMap.chrome;
-       } else if ( /\b\d+(\.\d+)+ safari/i.test( userAgent ) ) {
-               expected = expectedMap.safari;
        } else if ( /firefox\/102\./i.test( userAgent ) ) {
                expected = expectedMap.firefox_102;
        } else if ( /firefox/i.test( userAgent ) ) {
                expected = expectedMap.firefox;
        } else if ( /(?:iphone|ipad);.*(?:iphone)? os \d+_/i.test( userAgent ) ) {
                expected = expectedMap.ios;
+       } else if ( typeof URLSearchParams !== "undefined" &&
+
+               // `karma-webkit-launcher` adds `test_browser=Playwright` to the query string.
+               // The normal way of using user agent to detect the browser won't help
+               // as on macOS Playwright doesn't specify the `Safari` token but on Linux
+               // it does.
+               // See https://github.com/google/karma-webkit-launcher#detected-if-safari-or-playwright-is-used
+               new URLSearchParams( document.referrer || window.location.search ).get(
+                       "test_browser"
+               ) === "Playwright"
+       ) {
+               expected = expectedMap.webkit;
+       } else if ( /\b\d+(\.\d+)+ safari/i.test( userAgent ) ) {
+               expected = expectedMap.safari;
        }
 
        QUnit.test( "Verify that support tests resolve as expected per browser", function( assert ) {
@@ -134,7 +150,8 @@ testIframe(
                for ( i in expected ) {
                        assert.equal( computedSupport[ i ], expected[ i ],
                                "jQuery.support['" + i + "']: " + computedSupport[ i ] +
-                                       ", expected['" + i + "']: " + expected[ i ] );
+                                       ", expected['" + i + "']: " + expected[ i ] +
+                                       ";\nUser Agent: " + navigator.userAgent );
                }
        } );