Svelte Component Testing with Jest, Unable to load Svelte files recursively - javascript

I am working on a Svelte Project with Typescript and want to use Jest to test UI components using the #testing-library/svelte module . I am not able to properly import all my svelte files like my sub-components and Jest just hangs trying to load the application.
There are some typescript errors in the svelte components and by these errors printing, I can see which files actually loaded. After loading App.svelte, the program just freezes and doesn't load any of the submodules.
I am not exactly sure where the error is, because before this error I was getting an import error similar to jest: Test suite failed to run, SyntaxError: Unexpected token import, I "solved" this by adding the configuration to the .babelrc file and adding the preprocessor.
All the relevant files are below and are also on Github here
The actual test case file, there is a data-testid element called dropzone in dropzone.svelte
// app.spec.js
import App from "../src/App.svelte";
import { render, fireEvent } from "#testing-library/svelte";
describe("UI Load Test", () => {
it("Check Dropzone Loaded", () => {
const { getByText, getByTestId } = render(App);
const dropzone = getByTestId("dropzone");
expect(dropzone).toBeDefined();
});
});
// App.svelte
<script lang="ts">
...
// Static Svelte Components
import HeaderContent from "./components/header.svelte";
import Loader from "./components/loader.svelte";
import Footer from "./components/footer.svelte";
// Dynamic Svelte Modules
import Terminal from "./modules/terminal/terminal.svelte";
import Dropzone from "./modules/dropzone/dropzone.svelte";
import Configure from "./modules/configure/configure.svelte";
import Video from "./modules/video/video.svelte";
import Progress from "./modules/progress/progress.svelte";
let loaded = $loadedStore;
...
let fileState = $fileUploaded;
...
let processedState = $processed;
...
let progressState = $progressStore;
...
let configState = $showConfig;
...
</script>
...
// jest.config.js
const {
preprocess: makeTsPreprocess,
createEnv,
readConfigFile,
} = require("#pyoner/svelte-ts-preprocess");
const env = createEnv();
const compilerOptions = readConfigFile(env);
const preprocessOptions = {
env,
compilerOptions: {
...compilerOptions,
allowNonTsExtensions: true,
},
};
const preprocess = makeTsPreprocess(preprocessOptions);
module.exports = {
transform: {
"^.+\\.svelte$": [
"jest-transform-svelte",
{ preprocess: preprocess, debug: true },
],
"^.+\\.ts$": "ts-jest",
"^.+\\.js$": "babel-jest",
},
moduleDirectories: ["node_modules", "src"],
testPathIgnorePatterns: ["node_modules"],
bail: false,
verbose: true,
transformIgnorePatterns: ["node_modules"],
moduleFileExtensions: ["js", "svelte", "ts"],
setupFilesAfterEnv: [
"./jest.setup.js",
"#testing-library/jest-dom/extend-expect",
],
};
// babel.config.js
module.exports = {
presets: [
[
"#babel/preset-env",
{
targets: {
node: "current",
},
},
],
],
};
//.babelrc
{
"plugins": [
"#babel/plugin-syntax-dynamic-import"
],
"env": {
"test": {
"plugins": ["dynamic-import-node"]
}
}
}

You have not imported these variables yet from your store.ts file "$loadedStore, $fileUploaded, $processed, $progressStore, $showConfig"
Basically, you can put this on a store.ts like this.
// store.ts
export const loadedStore= writable([]) // for arrays
export const fileUploaded= writable({}) // for objects
export const processed = writable("") // for strings
export const progressStore = writable("")
export const showConfig= writable({})
Then add this line on top of your App.svelte file
// App.svelte
import { loadedStore, fileUploaded, processed, progressStore, showConfig } from 'store.ts'

Related

How to configure Relay.JS in Vite?

I'm trying to migrate my React project from CRA to Vite, this is my vite.config.js:
import { defineConfig } from 'vite'
import react from '#vitejs/plugin-react'
import envCompatible from 'vite-plugin-env-compatible'
import relay from "vite-plugin-relay"
import macrosPlugin from "vite-plugin-babel-macros"
import path from 'path';
import fs from 'fs/promises';
export default defineConfig({
resolve: {
alias: {
'~': path.resolve(__dirname, 'src'),
'#material-ui/core': path.resolve(__dirname, 'node_modules/#material-ui/core')
}
},
esbuild: {
loader: "tsx",
include: /src\/.*\.[tj]sx?$/,
exclude: [],
},
optimizeDeps: {
esbuildOptions: {
plugins: [
{
name: "load-js-files-as-jsx",
setup(build) {
build.onLoad({ filter: /src\/.*\.js$/ }, async (args) => ({
loader: "tsx",
contents: await fs.readFile(args.path, "utf8"),
}));
},
},
],
},
},
define: {
global: {},
},
plugins: [
envCompatible(),
react(),
relay,
//macrosPlugin(),
],
})
My GraphQL query files are like this:
import graphql from 'babel-plugin-relay/macro'
const getQuery = () => graphql`
query UserQuery($id: ID!) {
user(id: $id) {
id
fullName
}
}
`
export default getQuery
When I tried to run the project in dev mode (command $ vite), I got this error:
So I did some search and replaced vite-plugin-relay to vite-plugin-babel-macros like this:
// others import
import relay from "vite-plugin-relay"
import macrosPlugin from "vite-plugin-babel-macros"
export default defineConfig({
// configs like bellow
plugins: [
envCompatible(),
react(),
//relay,
macrosPlugin(),
],
})
So I started to get a new error:
How can I configure Relay to work on Vite.JS?
Might be a bit late, but the issue has been fixed in Relay#13 and you can find some workarounds in this thread for older versions of Relay :
https://github.com/facebook/relay/issues/3354
You can also try adding the option eagerEsModules: true to your relay babel plugin configuration.
Unless you have some specific usecase that requires the use of babel-plugin-relay, your issue should be resolved if you change your imports from
import graphql from 'babel-plugin-relay/macro'
to
import { graphql } from "react-relay";
You should only need the relay vite plugin at that point, and can remove vite-plugin-babel-macros
There's a few things wrong with your setup.
1. Don't use vite-plugin-babel-macros:
Use #vitejs/plugin-react instead.
import { defineConfig } from "vite";
import react from "#vitejs/plugin-react";
import relay from "vite-plugin-relay";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [relay, react({
babel: {
plugins: ['babel-plugin-macros']
},
})],
});
You can probably get it to work with vite-plugin-babel-macros, but the later is an official plugin.
2. Don't use 'babel-plugin-relay/macro':
Use the following instead:
import { graphql } from "react-relay";
It's unclear to me why the official docs suggest using babel-plugin-relay/macro, but that just doesn't work.
3. Configure relay.config.js correctly:
{
"src": "./src",
"language": "typescript",
// Change this to the location of your graphql schema
"schema": "./src/graphql/schema.graphql",
"exclude": [
"**/node_modules/**",
"**/__mocks__/**",
"**/__generated__/**"
],
"eagerEsModules": true
}
In particular, make sure you use language: typescript and eagerEsModules.
4. Sample repository
I wrote a sample repository showing how to properly configure React Relay with Vite.js and TypeScript, you can find it here.

Rollup imported css in a webcomponent

I am creating simple webcomponent now I want to import css , I found a method using adpotedstylesheet.
Here is how I import it my webcomponet
import sheet from './styles/swal.css' assert { type: 'css' };
class Demo extends HTMLElement{
constructor() {
this.attachShadow({ mode: "open" });
this.shadowRoot.appendChild(Demo.content.cloneNode(true));
document.adoptedStyleSheets = [sheet];
this.shadowRoot.adoptedStyleSheets = [sheet];
}
}
window.customElements.define("demo-component", Demo);
and here is my rollup settup for bundling my component
import summary from "rollup-plugin-summary";
import { terser } from "rollup-plugin-terser";
import resolve from "#rollup/plugin-node-resolve";
import replace from "#rollup/plugin-replace";
import postcss from "rollup-plugin-postcss";
import { eslint } from "rollup-plugin-eslint";
import babel from "rollup-plugin-babel";
import { uglify } from "rollup-plugin-uglify";
import commonjs from 'rollup-plugin-commonjs';
export default {
input: "index.js",
output: {
file: "dist/index.js",
format: "esm",
},
onwarn(warning) {
if (warning.code !== "THIS_IS_UNDEFINED") {
console.error(`(!) ${warning.message}`);
}
},
plugins: [
postcss({
plugins: [],
extensions: [".css"],
}),
resolve({
jsnext: true,
main: true,
browser: true,
}),
commonjs(),
eslint({
exclude: ["src/styles/**"],
}),
babel({
exclude: "node_modules/**",
}),
terser({
ecma: 2017,
module: true,
warnings: true,
mangle: {
properties: {
regex: /^__/,
},
},
}),
summary(),
replace({
"Reflect.decorate": "undefined",
preventAssignment: true,
ENV: JSON.stringify(process.env.NODE_ENV || "development"),
}),
process.env.NODE_ENV === "production" && uglify(),
],
};
Now when i run npm run buil I get the following error.
[!] (plugin commonjs) SyntaxError: Unexpected token (3:38)`
What am I doing wrong here ???
Currenly, Rollup doesn't support import assertions. There is open issue for Rollup to address it. There is an experimental Rollup plugin that supports this but it seems to have some issues.
Another option you can try is to use rollup-string-plugin. You can use it to read CSS file as a string and then build your constructible stylesheets and assign it to adoptedStyleSheets property as explained here for Webpack. Following is one example of doing it..
// Read SCSS file as a raw CSS text
import styleText from './my-component.css';
const sheet = new CSSStyleSheet();
sheet.replaceSync(styleText);
// Custom Web component
class FancyComponent1 extends HTMLElement {
constructor() {
super();
const shadowRoot = this.attachShadow({ mode: 'open' });
// Attaching the style sheet to the Shadow DOM of this component
shadowRoot.adoptedStyleSheets = [sheet];
shadowRoot.innerHTML = `
<div>
<p>Hello World</p>
</div>
`;
}
}
Side note: With Webpack, you can use raw-loader.
Be aware that adoptedStyleSheets is currently not supported by Safari on Mac and iOS. But, Rollup might handle this for you - I don't know.
Another solution is to check out:
https://www.npmjs.com/package/csshtml-module
This CLI tool can be set up to let you automatically compile CSS/HTML to native JS modules.
I created that CLI tool to tackle this issue. It might not be for everyone - but maybe it resonate with you.

React Native - Jest - Enzyme throws an Jest cannot parse Error

i'm facing an error when i want to add Jest and Enzyme as a testing library to my React Native project. This is my codes :
//Button.spec.js
import React from 'react';
import { View } from 'react-native';
import { shallow } from 'enzyme';
const Test = () => <View />;
describe('SomeComponent component', () => {
it('Shallow rendering', () => {
const wrapper = shallow(<Test />);
});
});
//jest/setup.js
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Enzyme.configure({ adapter: new Adapter() });
//babel.config.js
module.exports = () => ({
presets: ['module:metro-react-native-babel-preset'],
plugins: ['transform-flow-strip-types']
});
//jest.config.json
{
"preset": "react-native",
"collectCoverage": true,
"moduleDirectories": [
"node_modules",
"src"
],
"transform": {
"^.+\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor.js"
},
"setupFiles": [
"<rootDir>/jest/setup.js"
],
"transformIgnorePatterns": [
"/node_modules/(?!react-native|).+\\.js$"
],
"coveragePathIgnorePatterns": [
"/node_modules/",
"/jest"
]
}
When I run npm test. It will throws an error like this :
/src/components/common/__test__/Button.spec.js: Unexpected token (5:19)
Jest encountered an unexpected token
This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.
By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".
Here's what you can do:
• To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
• If you need a custom transformation specify a "transform" option in your config.
• If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/en/configuration.html
Details:
3 | import { shallow } from 'enzyme';
4 |
> 5 | const Test = () => <View />;
| ^
6 |
7 | describe('SomeComponent component', () => {
8 | it('Shallow rendering', () => {
Do you guys have any suggestions to fix this? Should I add any library I used inside node_modules to transformIgnorePatterns? Or is there any missing step to setup?

#storybook/angular cannot load scss file on stories index

I have been trying to use storybook for my angular project and I use this guide https://storybook.js.org/basics/guide-angular/
I use the recommended config for webpack for sass loader for scss files and the scss file related to the project works fine, but if I import a scss file in the stories index.ts file, this file it is not loaded.
stories/index.ts
import { storiesOf } from '#storybook/angular';
import { action } from '#storybook/addon-actions';
import { VideoPosterComponent } from '../src/app/modules/ui-common/video-poster/video-poster.component';
//This scss it is not loaded
import '../src/styles.scss';
storiesOf('Video Poster component', module)
.add('Video Poster with author data', () => ({
component: VideoPosterComponent,
props: {
title: "Cinemagraph With Custom title",
subtitle: "This is a custom subtitle!"
}
}))
.add('Video Poster without author data', () => ({
component: VideoPosterComponent,
props: {}
}));
.storybook/webpack.config.js (recommended in here --> https://storybook.js.org/basics/guide-angular/#configure-style-rules)
const genDefaultConfig = require('#storybook/angular/dist/server/config/defaults/webpack.config.js');
module.exports = (baseConfig, env) => {
const config = genDefaultConfig(baseConfig, env);
// Overwrite .css rule
const cssRule = config.module.rules.find(rule => rule.test && rule.test.toString() === '/\\.css$/');
if (cssRule) {
cssRule.exclude = /\.component\.css$/;
}
// Add .scss rule
config.module.rules.unshift({
test: /\.scss$/,
loaders: ['raw-loader', 'sass-loader'],
});
return config;
};
And, the scss file for my component was loaded without problems
src/app/modules/ui-common/video-poster/video-poster.component.ts
import { Component, OnInit, Input } from '#angular/core';
#Component({
selector: 'app-video-poster',
templateUrl: './video-poster.component.html',
styleUrls: ['./video-poster.component.scss'] // this were loaded without problems
})
export class VideoPosterComponent implements OnInit {
private hostUrl = 'https://s3-eu-west-1.amazonaws.com/video.gallereplay.com/portfolio/clients';
private baseUrl = `${this.hostUrl}/jaegermeister/Cinemagraph_plain/1920x1080`;
#Input()
public videoUrls = {
poster: `${this.baseUrl}/cinemagraph.jpg`,
mp4: `${this.baseUrl}/cinemagraph.mp4`,
webm: `${this.baseUrl}/cinemagraph.webm`,
}
#Input() public title = 'Custom Cinemagraph Productions';
#Input() public subtitle = 'Exclusive Content for Businesses';
constructor() { }
ngOnInit() {
}
}
Repository:
https://github.com/gpincheiraa/storybook-components-sample
run npm install && npm run storybook for check storybook running.
What I am doing wrong??
I assume that, like me, you're looking for a way to load global styles from SASS files into an Angular Storybook. I know it's been a while since you asked, but I came across this solution while searching for a way to accomplish this: https://github.com/storybookjs/storybook/issues/6364#issuecomment-485651328.
Basically, you can load your global styles in the Storybook config file. However, you need to use inline webpack loaders in the import path so Storybook will load them properly.
import '!style-loader!css-loader!sass-loader!../src/styles.scss';
That did the trick for me. In the end I didn't have to bother with the custom webpack config. Hopefully that solves your problem!
You are trying to import an scss file from your typescript. You must include it from your scss.
Please remove :
//This scss it is not loaded
import '../src/styles.scss';
In your scss file add :
#import "styles.scss";
In you angular.json add :
"styles": [
"src/styles.scss",
],
"stylePreprocessorOptions": {
"includePaths": [
"src/" // maybe not required in your case
]
},
In you .storybook/webpack.config.js please try :
const path = require("path");
module.exports = {
module: {
rules: [
{
test: /\.scss$/,
loaders: ["sass-loader"],
include: path.resolve(__dirname, "../src/")
}
]
}
};
Otherwise there is the possibility to add an alias as Xdecus said here https://github.com/storybooks/storybook/issues/3814#issuecomment-401756776
const path = require('path');
module.exports = {
resolve: {
alias: {
styles: path.resolve(__dirname, '../src/')
}
}
};
All style imports must be in Component metadata (specifically in styles or styleUrls field). You're trying to import style file as js file, which is wrong.

Inversify.js - Reflect.hasOwnMetadata is not a function

I'm trying out Inversify.js for a Typescript application I'm using. Right now, there is no framework involved, so it's pure ES2015.
I'm trying to follow along the example in the main page, but I'm being hit with:
"Reflect.hasOwnMetadata is not a function" when I try to run it in the browser.
I'm using Webpack as package bundler.
Here is my folder structure:
Here is the main app.ts file:
/// <reference path="../typings/index.d.ts" />
/// <reference path="./domain/abstract/match.interface.ts" />
import kernel from "../inversify/inversify.config.ts";
import {symbols} from "../inversify/symbols.ts";
var ninja = kernel.get<INinja>("INinja");
ninja.fight();
ninja.sneak();
interfaces.d.ts:
interface INinja {
fight(): string;
sneak(): string;
}
interface IKatana {
hit(): string;
}
interface IShuriken {
throw();
}
inversify.config.ts
/// <reference path="../node_modules/inversify/type_definitions/inversify/inversify.d.ts" />
/// <reference path="../node_modules/reflect-metadata/reflect-metadata.d.ts" />
/// <reference path="inversify.ts" />
import {Kernel} from "inversify"
//import {MatchHub} from "../app/components/Hubs/match/match-hub.component.ts";
//import {symbols} from "./symbols.ts";
import {Ninja, Katana, Shuriken} from "./inversify.ts";
var kernel = new Kernel();
kernel.bind<INinja>("INinja").to(Ninja);
kernel.bind<IKatana>("IKatana").to(Katana);
kernel.bind<IShuriken>("IShuriken").to(Shuriken);
export default kernel;
symbols.ts:
export const symbols = {
Match : Symbol("Match")
}
tsconfig.json:
{
"compilerOptions": {
"noImplicitAny": false,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"removeComments": true,
"sourceMap": true,
"target": "es5"
},
"exclude": [
"node_modules",
"bower_components",
"wwwroot"
]
}
Webpack.config.js:
module.exports = {
entry: './app/app.ts',
output: {
filename: '../Scripts/app/app.js'
},
resolve: {
extensions: ['', '.Webpack.js', '.web.js', '.ts','.js', '.tsx']
},
module: {
loaders: [
{
test: /\.ts?$/,
exclude: /(node_modules|bower_components)/,
loader: 'ts-loader'
}
]
},
watch: true
}
Firefox Console Error:
Webpack output:
When I tried to install Inversify the following warnings popped up:
Is it a bug? Or am I doing something wrong? Thanks!
PS: Tried following the sample files, but I couldn't understand anything!
I come from ASP.NET MVC 5 with Ninject so I can relate for most of the syntax.
It seems you will need to include the reflect-metadata package. Try adding an import to it in inversify.config.ts by doing:
import "reflect-metadata";
May be a silly thing to point out, I ran into a the same issue but it was because of the order of imports.
Its unlikely to be the case for any other imports but in case of reflect-metadata it has to be imported before any classes that use it.
import { Container } from "inversify";
//reflect-metadata should be imported
//before any interface or other imports
//also it should be imported only once
//so that a singleton is created.
import "reflect-metadata";
import Battle from "./interfaces/battle";
import EpicBattle from "./interfaces/epic_battle";

Categories

Resources