Has any one gotten #marko/testing-library to work with vitetest? - vite

I have a project in Vite, Fastify and Marko and am trying to use Vitest.
I want to test individual components/templates. Say pass in inputs (props) and test if the output (typically HTML) is as expected.
The Marko Testing Library supplies this but currently, with Vitest, it does not recognize the inputs. It returns an error when trying to "render" the template, saying:
TypeError: Cannot read properties of undefined (reading 'session')
❯ _marko_template._.__vite_ssr_import_4__.default.t src/components/menu-main/menu-main.marko:13:16
11| </li>
12| <li>
13| <if(input.session.firebaseAuthenticated)>
| ^
14| ${ input.session.displayName} Logout
15| </if>
❯ renderer node_modules/marko/dist/runtime/components/renderer.js:218:5
❯ proxyRenderer node_modules/marko/dist/runtime/vdom/hot-reload.js:73:21
❯ Proxy.renderTagHelper node_modules/marko/dist/runtime/helpers/render-tag.js:15:77
❯ _marko_template._.__vite_ssr_import_5__.default.t src/components/menu-main/menu-main.marko?marko-server-entry:8:3
❯ renderer node_modules/marko/dist/runtime/components/renderer.js:218:5
❯ proxyRenderer node_modules/marko/dist/runtime/vdom/hot-reload.js:73:21
❯ safeRender node_modules/marko/dist/runtime/renderable.js:7:5
❯ Template.render node_modules/marko/dist/runtime/renderable.js:139:14
❯ renderResult node_modules/#marko/testing-library/dist/cjs/index-browser.js:59:72
❯ Proxy.render node_modules/#marko/testing-library/dist/cjs/index-browser.js:59:30
❯ src/components/menu-main/menu-main.test.js:8:30
If, in the template, I check "all the way up the chain" (as I should) in my conditional this error goes away.
<if(input?.session?.isXYZ)>
<a ...>Log Out</a>
</if>
<else>
<a ...>Log In</a>
</else>
But of course I am very explicitly (trying) to pass in input.session.isXYZ as true.
In any case, then the error changes to:
TypeError: Cannot read properties of undefined (reading 'id')
❯ morphChildren node_modules/marko/dist/runtime/vdom/morphdom/index.js:269:41
❯ morphdom node_modules/marko/dist/runtime/vdom/morphdom/index.js:684:3
❯ AsyncVDOMBuilder.B_ node_modules/marko/dist/runtime/vdom/AsyncVDOMBuilder.js:394:7
❯ RenderResult.getNode node_modules/marko/dist/runtime/RenderResult.js:61:20
❯ getEl node_modules/marko/dist/runtime/RenderResult.js:106:23
❯ RenderResult.appendTo node_modules/marko/dist/runtime/dom-insert.js:31:16
❯ Proxy.render node_modules/#marko/testing-library/dist/cjs/index-browser.js:61:33
❯ async /home/ee/code/dibbs/dibbs-marko/src/components/menu-main/menu-main.test.js:11:25
But there is no reference to id in that component.
Even if I make the component just <div></div>
I get this id error. I assume it must be looking beyond the component/template I imported into my test script and am trying to test on.
I can look at node_modules/marko/dist/runtime/vdom/morphdom/index.js:269:41 etc of course but before I go down that rabbit hole, I wanted to ask here. Any ideas?
The testing Script:
import { render } from "#marko/testing-library";
import template from "./menu-main.marko";
import { test } from 'vitest'
test('login menu item shows correct state', async (ctx) => {
const { container } = await render(template, {
session: {
firebaseAuthenticated: false,
}
});
expect(container).stringContaining("Log In");
})

Related

Git/node getting stuck on old .js -file version

I'm having a weird problem with git/node getting stuck to use an old version of .js-file.
Every once in a while after saving changes (so far only when the code has some errors in it, often after merge conflicts) the file gets somehow stuck in old version when building the app. Everything looks to be ok, VSCode changes the file and shows it just fine, but when trying to build the app, build process (both develop and production) uses the old fileversion with bugs in it.
This same thing is happening both on Win10 and MacOs.
I have found 2 ways to fix this (both are just workarounds)
Rename the file that is causing the problem
the old filename cannot be used even after it has been deleted and recreacted
Clone the branch with new name Re-clone the repository
Here are example files:
InfoComponents.js (this one had the error in it)
import React from 'react';
import Typography from '#material-ui/core/Typography';
import Battery from '#navigil/shared/src/components/SVGs/Battery';
import Box from '#navigil/shared/src/components/Box/Box';
import InfoBadge from './InfoBadge';
const batteryStatus = [80, 50, 15, 5];
const InfoComponents = ({ badges }) => (
<>
<Typography variant='h4'>Status / Warnings / Alarms</Typography>
<Box>
{badges.map((badge, index) => {
const { badgeProps, imageProps, imageComponent: Image } = badge;
return (
<InfoBadge key={index} {...badgeProps}>
<Image {...imageProps} />
</InfoBadge>
);
})}
</Box>
</>
);
export default InfoComponents;
Dashboard.js (this imports InfoComponents)
import React from 'react';
import Typography from '#material-ui/core/Typography';
import styled from 'styled-components';
import Battery from '#navigil/shared/src/components/SVGs/Battery';
import Box from '#navigil/shared/src/components/Box/Box';
import Button from '#navigil/shared/src/styledTheme/Components/Button';
import InfoComponents from './InfoComponents';
import { badges } from './testVariables';
const StyledButton = styled(Button)`
max-width: 100px;
`;
const NewWatchDashboard = () => (
<>
<InfoComponents badges={badges} />
</>
);
export default NewWatchDashboard;
And here is the parse error i'm receiving when build fails:
./src/InfoComponents/Dashboard.js
Line 7:28: Parse errors in imported module './InfoComponents': Line 14: Unexpected token
12 | <Box>
13 | {badges.map((badge, index) => ({
> 14 | <InfoBadge key={index} {...badgeProps}>
| ^
15 | <Image {...imageProps} />
16 | </InfoBadge>;
17 | }))} (14:9) import/namespace
Line 7:28: Parse errors in imported module './InfoComponents': Line 14: Unexpected token
12 | <Box>
13 | {badges.map((badge, index) => ({
> 14 | <InfoBadge key={index} {...badgeProps}>
| ^
15 | <Image {...imageProps} />
16 | </InfoBadge>;
17 | }))} (14:9) import/default
As you can see from above, the code in InfoComponents.js doesn't match the code in error message.
Creating a sandbox for this is kind of hard, because everything works just fine if I'm creating all of this from scratch. So it definetly looks to be a problem with Git.
Any ideas what could cause this and how to prevent it from happening?
Any ideas how to fix this easily when it happens?
-Jukka
Most probably the issue is with your local Git working tree.
Give a try with following:
#Copy the code from `InfoComponents.js` to some other file.
git rm --cached InfoComponents.js
#Commit the change
# add back the file with backed up content
# commit again
This might solve the issue.
Or
Try to clean your local git work tree:
git gc --prune=now
And check if your changes are reflected correctly.

How to resolve Uncaught ReferenceError: COLLECTION is not defined at <anonymous>:1:1 in Meteor.js/MongoDB

I am taking a full stack course via Eduonix.com. It seems that some of the code syntax is deprecated, as I have had to install older versions of multiple things to get through some of the sections. This did not help when I came to the Meteor.js section, so I installed the most recent and did some searching that allowed me to get through the first lesson. I tried the same for the second lesson (when I encountered this error), but have not had any luck with anything I have found.
I get this error when I try to use
todos.find().fetch()
in the browser's console.
Relevant File Structure:
client
--main.html
--main.js
lib
--collections.js
View on github
In the course lesson, the line
import { Todos } from '../lib/collections';
is not present in main.js and the line
export const Todos = new Mongo.Collection('todos');
in collections.js is presented as
Todos = new Mongo.Collection('todos');
I have tried changing
import { Todos } from '../lib/collections';
to
import { Todos } from '/lib/collections';
but it did nothing.
I have also tried just adding
Todos = new Mongo.Collection('todos');
to main.js, but I got an error that said "todos" was already defined (only to get the same undefined error when I tried to run the console command, because somehow it was both already defined and is still undefined).
I have made these changes based on looking up similar issues online before making this post, hoping that it would save me like adding
import './main.html';
to main.js did when I was getting a similar undefined error related to that prior to this error.
main.html
<head>
<title>QuickTodos</title>
</head>
<body>
{{> main}}
</body>
<Template name="main">
<header>
<h1>{{title}}</h1>
</header>
<ul>
{{#each todos}}
{{> todo}}
{{/each}}
</ul>
</template>
<template name="todo">
<li>{{text}}</li>
</Template>
main.js
import { Template } from 'meteor/templating';
import './main.html';
import { Todos } from '../lib/collections';
const todos = [
{text:'Pickup kids from school'},
{text:'Go food shopping'},
{text:'Meeting with boss'}
];
Template.main.helpers({
title(){
return 'QuickTodos';
},
todos(){
return todos;
}
});
collections.js
import {Mongo} from 'meteor/mongo';
export const Todos = new Mongo.Collection('todos');
When I run
todos.find().fetch()
I expect to get an empty array, but instead I get:
VM1905:1
Uncaught ReferenceError: todos is not defined
at <anonymous>:1:1
What am I doing wrong?
The first thing I notice is that the capitalization of these two lines are different, meaning they will point to different variables (thus, todos is not defined):
export const Todos = new Mongo.Collection('todos');
todos.find().fetch()
The second thing, is that because Meteor uses CommonJS modules, any variables you declare will be local to that module, and won't be available on the console.
(there's some exceptions, like the Todos declared without var, let, or const, which will be scoped across the whole application, but still not global or available in the console)
You can force a variable to be global by adding it as a property to the window:
import { Mongo } from 'meteor/mongo';
export const Todos = new Mongo.Collection('todos');
window.Todos = Todos; // here we make it global
And then as long as this file is imported by client/main.js, you can use Todos on the console.
This is fine for small apps and testing stuff, but increases the likelihood of name collisions and makes it harder to understand where code is coming from in larger apps.
If you want to do things the "right" way for a module system, you can access the exports of a module in the console with require:
> Todos = require('/lib/collections').Todos

My file is failing right at the very first line, import React from "react", with a TypeError: Object(...) is not a function

I'm working with the basic Gatsby starter site and it compiles just fine, but the browser just shows the error mentioned in the title as well as a couple warnings.
It's probably important to note that the error is gone when I completely remove the StaticQuery piece so the IndexPage component is just the opening and closing Layout tags. This gets rid of the error and the browser shows the header+footer of the Gatsby starter site.
I've made sure that my versions of react and react-dom are up to date in the package.json, I've reinstalled the packages via npm install, I've tried other versions of react, nothing is working.
The file that is failing (index.js):
import React from "react"
import { StaticQuery, GraphQL, Link } from "gatsby"
import Layout from "../components/layout"
import Image from "../components/image"
import SEO from "../components/seo"
const IndexPage = () => (
<Layout>
<StaticQuery query={GraphQL`{
allWordpressPage {
edges {
node {
id
title
content
}
}
}
}`} render={props => (
<div> {props.allWordpressPage.edges.map(page => (
<div key={page.node.id}>
<h1>
{page.node.title}
</h1>
<div dangerouslySetInnerHTML={{__html: page.node.content}} />
</div>
))}
</div>
)}
/>
</Layout>
)
export default IndexPage
The error and warnings that show in browser:
TypeError: Object(...) is not a function
IndexPage
src/pages/index.js:1
> 1 | import React from "react"
2 | import { Link } from "gatsby"
3 |
4 | import Layout from "../components/layout"
View compiled
▶ 17 stack frames were collapsed.
JSONStore._this.handleMittEvent
/Users/kennansmith/Desktop/Temp_Task_Folder/gatsby-wp/.cache/json-store.js:1
> 1 | import React from "react"
2 |
3 | import PageRenderer from "./page-renderer"
4 | import normalizePagePath from "./normalize-page-path"
View compiled
▶ 2 stack frames were collapsed.
r.<anonymous>
/Users/kennansmith/Desktop/Temp_Task_Folder/gatsby-wp/.cache/socketIo.js:20
17 | // Try to initialize web socket if we didn't do it already
18 | try {
19 | // eslint-disable-next-line no-undef
> 20 | socket = io()
21 |
22 | const didDataChange = (msg, queryData) => {
23 | const id =
View compiled
▶ 24 stack frames were collapsed.
Maybe these imports are not the default ones?
import Layout from "../components/layout"
import Image from "../components/image"
import SEO from "../components/seo"
check if they ere exported as default, otherwise you shuld use {} import
Ok, got it working again.
The issue was that I was using GraphQL instead of graphql. The case-sensitivity was throwing the whole thing off. Replacing both instances of GraphQL with graphql fixed the issue and now I am seeing my data rendered on the page as intended.

Locating element inside Span tag in Reactjs non angular site using Protractor

I need to click on "login" which is inside span tag, code looks like
<div data-reactroot>
<div class "ant-dropdown ant-dropdown-placement-bottomRight ant-dropdown-hidden" style="left 632.234px; top 65px;">
<ul class="ant-dropdown-menu ant-dropdown-menu-light ant-dropdown-menu-root ant-dropdown-menu-vertical" role="menu" style="border" 1px solid rgba(0, 0, 0, 0.23);">
<li class="ant-dropdown-menu-item" role="menuitem">...</li>
<li class=" ant-dropdown-menu-item-divider"></li>
<li class="ant-dropdown-menu-item" role="menuitem">...</li>
<span>Login</span>
</li>
https://i.stack.imgur.com/qDt4z.png
I tried using the code below, it does not work:
browser.driver.findElement(by.cssContainingText('ant-dropdown-menu-item', 'Login'))
I'm getting an error see below:
Message:
Failed: Invalid locator
Stack:
TypeError: Invalid locator
Try that:
browser.driver.findElement(by.cssContainingText('.ant-dropdown-menu-item', 'Login'))
In css selectors class need to have ..
Edit:
browser.driver.findElement(by.css('.ant-dropdown-menu-item > span'))
It's now working i'm tried using the following code below
element(by.xpath("//span[. = 'Login']")).click();
ReactJS testing made more simplifies with protractor-react-selector
protractor-react-selector is a lightweight plugin to help you to locate web elements in your REACT app using props and states.
You need to install the plugin with
npm i -D protractor-react-selector
Then, you need to add the plugin to the configuration file:
exports.config = {
// ... the rest of your config
plugins: [
{
package: 'protractor-react-selector'
}
]
}
Then, in a beforeAll`` hook or inside anonPrepare``` hook, wait for React to be loaded in your application like:
beforeAll(() => {
await browser.get('http://localhost:3000/myApp')
await browser.waitForReact()
})
Then you can use element(by.react) to fetch the react elements.
const myElement = element(
by.react('MyComponent', { someBooleanProp: true }, { someBooleanState: true })
)
myElement.click();
For testing the React element, you should not rely on the HTML DOM structure as most of the developers uses material tools that creates dynamic HTML runtime.
To find more example, visit these tests
A complete blog can be found here.

templateData variables return undefined from helper function (docpad.coffee configuration file)

This is my configuration file.
docpadConfig = {
templateData:
site:
title: 'hello docpad'
getTitle: ->
#site.title
getString: ->
'just a string'
}
# Export the DocPad Configuration
module.exports = docpadConfig
From a jade layout when I do title= site.title it renders ok. When I try to call the helper function title= getTitle() the console outputs this:
error: An error occured:
ReferenceError: /Volumes/Data/project/am/lab/docpad/hello_docpad/src/layouts/default.html.jade:21
19|
20| //- Our site title and description
> 21| title= getTitle()
22|
23| //- Output DocPad produced meta elements
24| != getBlock('meta').toHTML()
site is not defined
at docpadConfig.templateData.getWat (/Volumes/Data/project/am/lab/docpad/hello_docpad/docpad.coffee:10:16)
at eval (eval at <anonymous> (/Volumes/Data/project/am/lab/docpad/hello_docpad/node_modules/docpad-plugin-jade/node_modules/jade/lib/jade.js:170:8), <anonymous>:47:64)
Looks like I can't access the site object from inside the helper function.
I'm sure I'm missing something trivial, maybe a plugin is needed for this... can't find out "wat" is wrong here.
I've found the solution looking into a similar issue in a docpad skeleton. This relates to a bug in the Jade pre-processor.
Update to "docpad-plugin-jade": "~2.4.1" fixes the issue.

Resources