Problem Summary
Storybook snapshot test on static storybook returning blank screenshots even though they look fine on localhost:8080 when I ran npx http-server storybook-static
Tech stack and relevant code
Vue 3
Vite
Storybook
Jest
Storyshots
Puppeteer
I have components and their respective stories. npm run storybook works perfectly fine. My storybook.spec.js is as follows:
import { imageSnapshot } from "#storybook/addon-storyshots-puppeteer"
import initStoryshots from "#storybook/addon-storyshots"
initStoryshots({
suite: "Image storyshots",
test: imageSnapshot(
storybookUrl: 'file://absolute/path/to/my/storybook-static'
)
})
I ran the following. fyi, I did not modify any file in storybook-static after running npm run build-storybook.
npm run build-storybook
npm run test
npm run test constitutes jest --config=jest.config.js test
Problem
Unfortunately, the screenshots I get are all blank and fail the snapshot test.
I suspect it might be due to a CORS error just like other Storybook users when they click <project-root>/storybook-static/index.html after running npm run build-storybook, to which I want to ask for a solution as well, because I wanna run test remotely on a headless server.
Note
I used absolute path because relative path caused a resource not found error during the testing process.
The problem is that you're running the tests from file:// instead of http://. So the URI is file:// and the img url ends up like this after applying some url logic: path.resolve(window.location, '/your-image.png') file:///your-image.png.
If this is the case you could change to http://. You can start a express server and serve the storybook-static folder from setupGlobal and then shut it down in teardownGlobal. Then you will need to change your storybookUrl to http://localhost:<some-port>.
None of the images were loading within my pipeline but worked fine locally, ended up being because the components were fetching images using a relative path <img src="/my-image" /> which apparently is not allowed using the file protocol.
I ended up doing 2 things:
Updating the static dirs directory to use the root by updating the main.js file in storybook
module.exports = {
staticDirs: [{ from: '../static', to: '/' }],
}
Added a script to remove the leading slash of images in the preview-head.html file from storybook
<script>
document.addEventListener('DOMContentLoaded', () => {
Array.from(document.querySelectorAll('img')).forEach((img) => {
const original = img.getAttribute('src');
img.setAttribute('src', original.replace('/', ''));
});
});
</script>
Another (arguably better) approach would be to run the tests through a server where you can access the images
Related
My unit test launch looks like this. As you can see I have exploited CLI options to install a VSIX my CICD has already produced, and then also tried to install ms-vscode-remote.remote-ssh because I want to re-run the tests on a remote workspace.
import * as path from 'path';
import * as fs from 'fs';
import { runTests } from '#vscode/test-electron';
async function main() {
try {
// The folder containing the Extension Manifest package.json
// Passed to `--extensionDevelopmentPath`
const extensionDevelopmentPath = path.resolve(__dirname, '../../');
// The path to the extension test runner script
// Passed to --extensionTestsPath
const extensionTestsPath = path.resolve(__dirname, './suite/index');
const vsixName = fs.readdirSync(extensionDevelopmentPath)
.filter(p => path.extname(p) === ".vsix")
.sort((a, b) => a < b ? 1 : a > b ? -1 : 0)[0];
const launchArgsLocal = [
path.resolve(__dirname, '../../src/test/test-docs'),
"--install-extension",
vsixName,
"--install-extension",
"ms-vscode-remote.remote-ssh"
];
const SSH_HOST = process.argv[2];
const SSH_WORKSPACE = process.argv[3];
const launchArgsRemote = [
"--folder-uri",
`vscode-remote://ssh-remote+testuser#${SSH_HOST}${SSH_WORKSPACE}`
];
// Download VS Code, unzip it and run the integration test
await runTests({ extensionDevelopmentPath, extensionTestsPath, launchArgs: launchArgsLocal });
await runTests({ extensionDevelopmentPath, extensionTestsPath, launchArgs: launchArgsRemote });
} catch (err) {
console.error(err);
console.error('Failed to run tests');
process.exit(1);
}
}
main();
runTests downloads and installs VS Code, and passes through the parameters I supply. For the local file system all the tests pass, so the extension from the VSIX is definitely installed.
But ms-vscode-remote.remote-ssh doesn't seem to be installed - I get this error:
Cannot get canonical URI because no extension is installed to resolve ssh-remote
and then the tests fail because there's no open workspace.
This may be related to the fact that CLI installation of multiple extensions repeats the --install-extension switch. I suspect the switch name is used as a hash key.
What to do? Well, I'm not committed to any particular course of action, just platform independence. If I knew how to do a platform independent headless CLI installation of VS Code:latest in a GitHub Action, that would certainly do the trick. I could then directly use the CLI to install the extensions before the tests, and pass the installation path. Which would also require a unified way to get the path for vs code.
Update 2022-07-20
Having figured out how to do a platform independent headless CLI installation of VS Code:latest in a GitHub Action followed by installation of the required extensions I face new problems.
The test framework options include a path to an existing installation of VS Code. According to the interface documentation, supplying this should cause the test to use the existing installation instead of installing VS Code; this is why I thought the above installation would solve my problems.
However, the option seems to be ignored.
My latest iteration uses an extension dependency on remote-ssh to install it. There's a new problem: how to get the correct version of my extension onto the remote host. By default the remote host uses the marketplace version, which obviously won't be the version we're trying to test.
I would first try with only one --install-extension option, just to check if any extension is installed.
I would also check if the same set of commands works locally (install VSCode and its remote SSH extension)
Testing it locally (with only one extension) also allows to check if that extension has any dependencies (like Remote SSH - Editing)
This question already has answers here:
Error message "error:0308010C:digital envelope routines::unsupported"
(50 answers)
Closed 12 months ago.
I'm having an issue with a Webpack build process that suddenly broke, resulting in the following error...
<s> [webpack.Progress] 10% building 0/1 entries 0/0 dependencies 0/0 modules
node:internal/crypto/hash:67
this[kHandle] = new _Hash(algorithm, xofLen);
^
Error: error:0308010C:digital envelope routines::unsupported
at new Hash (node:internal/crypto/hash:67:19)
at Object.createHash (node:crypto:130:10)
at BulkUpdateDecorator.hashFactory (/app/node_modules/webpack/lib/util/createHash.js:155:18)
at BulkUpdateDecorator.update (/app/node_modules/webpack/lib/util/createHash.js:46:50)
at OriginalSource.updateHash (/app/node_modules/webpack-sources/lib/OriginalSource.js:131:8)
at NormalModule._initBuildHash (/app/node_modules/webpack/lib/NormalModule.js:888:17)
at handleParseResult (/app/node_modules/webpack/lib/NormalModule.js:954:10)
at /app/node_modules/webpack/lib/NormalModule.js:1048:4
at processResult (/app/node_modules/webpack/lib/NormalModule.js:763:11)
at /app/node_modules/webpack/lib/NormalModule.js:827:5 {
opensslErrorStack: [ 'error:03000086:digital envelope routines::initialization error' ],
library: 'digital envelope routines',
reason: 'unsupported',
code: 'ERR_OSSL_EVP_UNSUPPORTED'
}
command terminated with exit code 1
I've tried googling ERR_OSSL_EVP_UNSUPPORTED webpack which yielded almost no useful results, but it did highlight an issue using MD4 as provided by OpenSSL (which is apparently deprecated?) to generate hashes.
The webpack.config.js code is as follows:
const path = require('path');
const webpack = require('webpack');
/*
* SplitChunksPlugin is enabled by default and replaced
* deprecated CommonsChunkPlugin. It automatically identifies modules which
* should be splitted of chunk by heuristics using module duplication count and
* module category (i. e. node_modules). And splits the chunks…
*
* It is safe to remove "splitChunks" from the generated configuration
* and was added as an educational example.
*
* https://webpack.js.org/plugins/split-chunks-plugin/
*
*/
/*
* We've enabled TerserPlugin for you! This minifies your app
* in order to load faster and run less javascript.
*
* https://github.com/webpack-contrib/terser-webpack-plugin
*
*/
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
mode: 'development',
entry: './src/js/scripts.js',
output: {
path: path.resolve(__dirname, 'js'),
filename: 'scripts.js'
},
devtool: 'source-map',
plugins: [new webpack.ProgressPlugin()],
module: {
rules: []
},
optimization: {
minimizer: [new TerserPlugin()],
splitChunks: {
cacheGroups: {
vendors: {
priority: -10,
test: /[\\/]node_modules[\\/]/
}
},
chunks: 'async',
minChunks: 1,
minSize: 30000,
name: 'true'
}
}
};
How do I change the hashing algorithm used by Webpack to something else?
I was able to fix it via:
export NODE_OPTIONS=--openssl-legacy-provider
sachaw's comment to Node.js v17.0.0 - Error starting project in development mode #30078
But they say they fixed it: ijjk's comment to Node.js v17.0.0 - Error starting project in development mode #30078:
Hi, this has been updated in v11.1.3-canary.89 of Next.js, please update and give it a try!
For me, it worked only with the annotation above.
I also want to point out that npm run start works with -openssl-legacy-provider, but npm run dev won't.
It seems that there is a patch:
Node.js 17: digital envelope routines::unsupported #14532
I personally downgraded to 16-alpine.
I had this problem too. I'd accidentally been running on the latest Node.js (17.0 at time of writing), not the LTS version (14.18) which I'd meant to install. Downgrading my Node.js install to the LTS version fixed the problem for me.
There is a hashing algorithm that comes with Webpack v5.54.0+ that does not rely on OpenSSL.
To use this hash function that relies on a npm-provided dependency instead of an operating system-provided dependency, modify the webpack.config.cjs output key to include the hashFunction: "xxhash64" option.
module.exports = {
output: {
hashFunction: "xxhash64"
}
};
Ryan Brownell's answer is the ideal solution if you are using Webpack v5.54.0+.
If you're using an older version of Webpack, you can still solve this by changing the hash function to one that is not deprecated. (It defaults to the ancient md4, which OpenSSL has removed support for, which is the root cause of the error.) The supported algorithms are any supported by crypto.createHash. For example, to use SHA-256:
module.exports = {
output: {
hashFunction: "sha256"
}
};
Finally, if you are unable to change the Webpack configuration (e.g., if it's a transitive dependency which is running Webpack), you can enable OpenSSL's legacy provider to temporarily enable MD4 during the Webpack build. This is a last resort. Create a file openssl.cnf with this content…
openssl_conf = openssl_init
[openssl_init]
providers = provider_sect
[provider_sect]
default = default_sect
legacy = legacy_sect
[default_sect]
activate = 1
[legacy_sect]
activate = 1
…and then set the environment variable OPENSSL_CONF to the path to that file when running Webpack.
It is not my answer really, but I found this workaround /hack/ to fix my problem Code Check in for a GitHub project... see the bug comments here.
I ran into ERR_OSSL_EVP_UNSUPPORTED after updating with npm install.
I added the following to node_modules\react-scripts\config\webpack.config.js
const crypto = require("crypto");
const crypto_orig_createHash = crypto.createHash;
crypto.createHash = algorithm => crypto_orig_createHash(algorithm == "md4" ? "sha256" : algorithm);
I tried Ryan Brownell's solution and ended up with a different error, but this worked...
This error is mentioned in the release notes for Node.js 17.0.0, with a suggested workaround:
If you hit an ERR_OSSL_EVP_UNSUPPORTED error in your application with Node.js 17, it’s likely that your application or a module you’re using is attempting to use an algorithm or key size which is no longer allowed by default with OpenSSL 3.0. A command-line option, --openssl-legacy-provider, has been added to revert to the legacy provider as a temporary workaround for these tightened restrictions.
I ran into this issue using Laravel Mix (Webpack) and was able to fix it within file package.json by adding in the NODE_OPTIONS=--openssl-legacy-provider (referenced in Jan's answer) to the beginning of the script:
package.json:
{
"private": true,
"scripts": {
"production": "cross-env NODE_ENV=production NODE_OPTIONS=--openssl-legacy-provider node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
},
"dependencies": {
...
}
}
Try upgrading your Webpack version to 5.62.2.
I faced the same challenge, but you just need to downgrade Node.js to version 16.13 and everything works well. Download LTS, not the current on Downloads.
I had the same problem with my Vue.js project and I solved it.
macOS and Linux
You should have installed NVM (Node Version Manager). If you never had before, just run this command in your terminal:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
Open your project
Open the terminal in your project
Run the command nvm install 16.13.0 or any older version
After the installation is completed, run nvm use 16.13.0
I faced the same problem in a project I developed with Next.js. For the solution, I ran the project as follows and I solved the problem.
cross-env NODE_OPTIONS='--openssl-legacy-provider' next dev
This means that you have the latest Node.js version. If you are using it for Docker then you need to change the image from
FROM node
to
FROM node:14
I am developing web crawler which could render Javascript websites and so I decided to use PupeeteerSharp, a .NET port of popular Node.JS headless Chrome browser Pupeeteer API. I am running Service Fabric's local development cluster on Windows 10 development machine and have one stateless service in my solution.
I've created Data folder under Service project's PackageRoot folder and put .local-chromium folder contents there (contains chrome.exe executable) so it deploys as independent data package of service.
I've also placed this XML config line in ServiceManifest.xml file:
<DataPackage Name="Data" Version="1.0.0" />
So far it looks good and headless browser content is copied to SFCluster Data package directory properly.
Then in my Stateless Service code I try to call Pupeeteer chromium executable as follows:
var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
Headless = true,
ExecutablePath = _chromiumPath // #$"{context.CodePackageActivationContext.GetDataPackageObject("Data").Path}\.local-chromium\Win64-706915\chrome-win\chrome.exe"
});
using (var page = (await browser.NewPageAsync()))
{
Response renderResponse;
try
{
renderResponse = await page.GoToAsync(webPage.AbsoluteUri, timeout);
if (renderResponse.Status != System.Net.HttpStatusCode.OK)
{
return new RenderResult(RenderStatus.OtherFailure);
}
// other code
}
catch (TimeoutException)
{
return new RenderResult(RenderStatus.Timeouted);
}
In this line: using (var page = (await browser.NewPageAsync())) my code (Thread) simply hangs without returning, in Debug console I see many thread exits, but no exception occurs. I was previously getting System.IO.FileNotFoundException when I was fixing some other errors regarding appropriate copying of chromium folder contents, but now these errors are gone so it seems that code find .exe but somehow cannot start headless mode of PupeeterSharp.
Does that mean that I cannot simply run external .exe chromium binary with Service Fabric's Native Application Model? Should I use Docker and Linux containers instead?
I want to configure the routes for my project via F3. First I installed him via Composer and then I used the instructions about routing engine from This and This.
Then in browser if I'm going to URL localhost/myproject/ it is working fine. But if I'm going to URL localhost/myproject/route1 it isn't working for me and gives 404 server status error. Why?
My code in "index.php":
require_once('vendor/autoload.php');
$f3 = \Base::instance();
$f3->route('GET /', function() {
echo '123';
});
$f3->route('GET /route1', function() {
echo '345';
});
$f3->run();
It is the easiest project without anything with only F3. Where I wrong?
make sure you got this .htaccess in your folder and in case that this does not help, comment in the RewriteBase / and adjust the path to match you sub-folder ("myproject").
I've been trying to run my tests using karma-chrome-launcher, but everytime I run my tests it throws this error:
INFO [launcher]: Starting browser Chrome
ERROR [launcher]: Cannot start Chrome
INFO [launcher]: Trying to start Chrome again (1/2).
ERROR [launcher]: Cannot start Chrome
INFO [launcher]: Trying to start Chrome again (2/2).
ERROR [launcher]: Cannot start Chrome
ERROR [launcher]: Chrome failed 2 times (cannot start). Giving up.
Here's my karma.conf.js code:
// Karma configuration
// Generated on Mon Mar 23 2015 14:04:19 GMT-0300 (BRT)
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: 'www',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
'lib/ionic/js/angular/angular.js',
'lib/ionic/js/angular/angular-animate.js',
'lib/ionic/js/angular/angular-sanitize.js',
'../node_modules/jasmine-core/lib/jasmine-core/jasmine.js',
'../node_modules/mock-local-storage/lib/mock-localstorage.js',
'../node_modules/angular-mocks/angular-mocks.js',
//'../node_modules/requirejs/require.js',
'lib/ionic/js/angular/angular-resource.js',
'lib/ionic/js/angular-ui/angular-ui-router.js',
'lib/ionic/js/ionic.js',
'lib/ionic/js/ionic-angular.js',
/*'../tests/libs/ngCordovaMocks.min.js',*/
'js/lib/ng-cordova.min.js',
'js/*.js',
'js/controllers/*.js',
'js/services/*.js',
'js/factory/*.js',
//'../tests/*.js',
'../tests/**/*.js'
],
// list of files to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress', 'html'],
htmlReporter: {
outputFile: '../tests/report/index.html'
},
// web server port
port: 9876,
plugins : [
'karma-junit-reporter',
'karma-jasmine',
'karma-phantomjs-launcher',
'karma-chrome-launcher'
//'karma-htmlfile-reporter'
],
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['PhantomJS'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false
});
};
I'm installing the module here: https://www.npmjs.com/package/karma-chrome-launcher
Thanks!
I had the same problem and tried a lot of the suggested solutions I found, but what finally solved it for me was to delete the node_modules folder and getting everything new via npm install.
Had the same issue with my build environment.
What i did is to follow the advice of Rafael Cichocki to enable the debugging:
logLevel: config.LOG_DEBUG
Then tried to launch the chrome-browser with exactly the same line that was visible int he debug output.
Turned out that chrome browser was crashing due to missing ttf fonts. So running:
apt-get install ttf-freefont
Solved that issue for me and karma started to launch chrome.
In Karma.conf.js, Increase timeouts to 60000
captureTimeout: 60000,
browserDisconnectTimeout: 60000,
browserDisconnectTolerance: 3,
browserNoActivityTimeout: 60000,
browsers: ['PhantomJS'], Here allowed browser is PhantomJs, but code is trying for Chrome, which is not a specified browser in the karma.conf.js.
Change karma.conf.js file :
browsers: ['PhantomJS','Chrome', 'ChromeHeadless'],
chrome- is for opening new chrome browser window.
ChromeHeadless- is for running tests without opening browser window
make sure Chrome is installed and added to PATH
Hope this helps
I noticed when I had this error that when I changed the spec file and saved it, it seemed to work again. I had a few errors in typescript that didn't break the tests (passing in null arguments to a virtual component instance constructor). I don't know if it was resolving the errors since they existed before when it was working, or if changing the file and saving it updated the cache.
So this could mean that clearing the cache in Chrome could also potentially resolve it. It's working now again for me so I can't check to verify.
Just in case you are running this behind a corporate proxy. Make sure you include your 0.0.0.0 in your NO_PROXY Environment variable.
Otherwise your test will first go out through your firewall where it will most likely not be able to reach 0.0.0.0. So just to be sure I include the following in my
NO_PROXY=127.0.0.1,localhost,0.0.0.0
Especially if you are running your tests in a container environment (e.g. your build pipeline) non set environment variables might be a common reason for ng test working fine on your local machine but failing to connect to google-chrome in the container.
If someone faces this error only in gitlab-runner (but in shell by hand ng test work ok), you can apply decision from here:
https://forum.gitlab.com/t/running-karma-tests-with-chrome-and-gitlab-ci/14476
The decision is: in karma.config.js, replace the section
browsers: ['Chrome'],
by
browsers: ['ChromeHeadlessNoSandbox'],
customLaunchers: {
ChromeHeadlessNoSandbox: {
base: 'ChromeHeadless',
flags: ['--no-sandbox']
}
},
The reason of error is that Chrome doesn't support no-sandbox anymore
I got my inspiration partially from here: https://stackoverflow.com/a/33802985/1534823
Also use logLevel: config.LOG_DEBUG - it can help you get good information on what is causing your error`
Check following settings in karma.conf:
captureTimeout: 60000,
browserNoActivityTimeout: 360000
browser: ["Firefox"]
captureTimeout - your browser may take some time to start. LOG_DEBUG should show some error related to capturing your browser
browserNoActivityTimeout - PhantomJS is really slow(x10) on my machine, in comparison to Firefox and Chrome. Karma may timeout before your tests complete.
browser - our jenkins server runs on linux, where we had no binaries for chrome, so we had to switch to firefox
If any of these three settings were not set correctly, we would get the error you described above.
I was able to resolve this by remove the absolute path (src/examplePath) and changing it to a relative path (../../examplePath).
Example change in spec:
import { myPackage } from 'src/myPath'; (seems to be the issues)
import { myPackage } from '../../../myPath'; (seems to resolve it)
Note I had tried deleting the node modules and npm installing but that didn't work. I'm so not sure why this matters.
In Windows Chrome was install to %LOCALAPPDATA%/Google/Chrome/Application earlier. Now it's install to %PROGRAMFILES%/Google/Chrome/Application. If you is very long time with Chrome then your have old version in %LOCALAPPDATA%/Google/Chrome/Application.
Karma-launcher is searches Chrome location in order LOCALAPPDATA->PROGRAMFILES-> 'PROGRAMFILES(X86)' , first found old version and try to run it.
Just delete %LOCALAPPDATA%/Google/Chrome/Application folder
Solution for us with angular cli was setting the following properties in the karma.conf.js
autoWatch: false,
singleRun: true
I was also facing this issue. I made below three changes in my karma.config.js file.
autoWatch: false,
browsers: ['Chrome'],
singleRun: false
I experienced this after updating macOS to Catalina. I solved it by updating Puppeteer to the latest version.
What worked for me:
npm un karma-chrome-launcher
npm i karma-chrome-launcher
npm i -g karma-cli
karma init (and follow the prompts)
ng test --watch=false
Using the watch flag set to false in combination with adjustment of the following parameters in karma.config.js worked for me:
browsers: ['ChromeHeadlessNoSandbox'],
customLaunchers: {
ChromeHeadlessNoSandbox: {
base: 'ChromeHeadless',
flags: ['--no-sandbox']
}
},
I faced a similar issue recently.
And found two solutions to fix this problem.
I installed puppeteer and added process.env.CHROME_BIN = require('puppeteer').executablePath() at the top of my karma.conf.js file, as documented here.
I uninstalled Google Chrome and cleared up all the system folders (%Local Appdata%\Google and also from Program Files / Program Files x86), restarted by the system, and then installed Chrome x64 from the official site.
I was happy with the 1st solution as well, but since I wanted to fix the root problem, I went ahead and found the second solution as well.
Hope this solves the problem for anyone facing this issue.