jest-expo-puppeteer - Getting "Oh no! It looks like JavaScript is not enabled in your browser" - react-native

When I run a very simple sample test in jest-expo-puppeteer following the guidelines in jest-expo-puppeteer documentation, I keep getting a log of weird errors, and it seems none of the elements expected could be found. So I tried to print out the page:
// Import the config so we can find the host URL
import config from '../../jest-puppeteer.config'
let response
beforeEach(async () => {
// Jest puppeteer exposes the page object from Puppeteer
response = await page.goto(config.url)
})
it(`should have welcome string`, async () => {
const html = await page.evaluate(() => document.documentElement.outerHTML)
console.log(html)
await expect(page).toMatchElement('div[data-testid="welcome"]', { text: 'Welcome!' })
})
The result of the page shows the text Oh no! It looks like JavaScript is not enabled in your browser.:
...
<body>
<!--
A generic no script element with a reload button and a message.
Feel free to customize this however you'd like.
-->
<noscript>
<form
action=""
style="background-color:#fff;position:fixed;top:0;left:0;right:0;bottom:0;z-index:9999;"
>
<div
style="font-size:18px;font-family:Helvetica,sans-serif;line-height:24px;margin:10%;width:80%;"
>
<p>Oh no! It looks like JavaScript is not enabled in your browser.</p>
<p style="margin:20px 0;">
<button
type="submit"
style="background-color: #4630EB; border-radius: 100px; border: none; box-shadow: none; color: #fff; cursor: pointer; font-weight: bold; line-height: 20px; padding: 6px 16px;"
>
Reload
</button>
</p>
</div>
</form>
</noscript>
<!-- The root element for your Expo app. -->
<div id="root"><div class="css-view-1dbjc4n r-flex-13awgt0 r-pointerEvents-12vffkv"><div class="css-view-1dbjc4n r-flex-13awgt0 r-pointerEvents-12vffkv"></div></div></div>
<script src="/static/js/bundle.js"></script>
</body></html>
...
This happens for both headless and in-browser execution.
So it looks like Javascript is turned off. The page object is created internally by jest-expo-puppeteer, so I wonder:
How to turn on JavaScript in jest-expo-puppeteer?
Shouldn't this be turned on by default? Perhaps there is something that I missed out in my setup?

I've found out the answer myself:
The content Oh no! It looks like JavaScript is not enabled in your browser. is always present in react-native file. It seems to server as a backup (in case the browser indeed doesn't have JavaScript enabled it will be shown).
Hence there is no need to turn on JavaScript. Indeed JavaScript is turned on by default.
The reason why I wasn't able to detect elements in my page is because JavaScript execution has not finished. When I put in a wait statement then it works fine, for example this:
it(`should have welcome string`, async () => {
const welcome = await page.waitForSelector('div[data-testid="welcome"]')
const text = await (await welcome.getProperty('innerHTML')).jsonValue()
await expect(text).toMatch('Welcome!')
})

Related

Can I create iframes tab menu using Nuxt?

I'm going to make Nuxt function like following sample code.
The work is being carried out without a good understanding of Nuxt.
It is not even using the tag <nuxt/>. Because it has to be made with iframe.
The reason why we want to use iframe is that we want existing information to remain even if the new content generated is tabbed.
The way I want to work doesn't seem to fit Nuxt's characteristics, but... I can't think of any other way.
The question I want is as follows.
Create tabMenu using Nuxt, and each tab content must maintain existing data even if the tab moves.
Is this possible with Nuxt?
// it just sample code, Not my question
$(function(){
function setPage(name,src){
const tabs = `<button role="button">${name}</button>`
const iframes = `<div>here is ifame area of ${name} page</div>`
$('.page-tab').append(tabs)
$('.page-frame').append(iframes)
}
function setView(number){
$('.page-frame > div').eq(number).removeClass('hide').siblings().addClass('hide')
}
$('.tab-content > li').click(function(){
const $this = $(this);
const index = $this.index()
const name = $this.text()
const src = $this.data('src')
setPage(name+index,src)
setView(index)
$('.page-tab button').click(function(){
setView($(this).index())
})
});
})
html,body,#sample {
height: 100%;
}
#sample {
display :flex;
}
aside {
flex: 0 0 auto;
height: 100%;
background-color:#eee;
}
.tab-content li {
text-align: center;
cursor: pointer;
padding: 10px 8px;
border-bottom: 1px solid #ddd;
}
main {
flex: 1 0 auto;
display: flex;
flex-direction:column;
}
.hide {
display: none !important;
}
<link href="https://cdn.jsdelivr.net/npm/reset-css#5.0.1/reset.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="sample">
<aside>
<ul class="tab-content">
<li role="button" data-src="https://www.reddit.com/">Apple</li>
<li role="button" data-src="https://finance.yahoo.com/quote/TSLA/">Orange</li>
<li role="button" data-src="https://github.com/dogecoin/dogecoin">Water</li>
</ul>
</aside>
<main>
<div class="page-tab"></div>
<div class="page-frame"></div>
</main>
</div>
You should really not try to do this in jQuery but in pure VueJS (or Nuxt, it's the same). Mixing declarative and imperative code is not a good idea.
For a tab functionality, you can use dynamic components to keep up the state while still toggling tabs.
I'm not sure if you're using SFC components or not, but here is a JSfiddle that may show you how to make tabs in VueJS: https://jsfiddle.net/chrisvfritz/Lp20op9o/

Barba.js & GSAP new element appears before old element is gone

I'm trying to implement the basic GSAP fade-in / fade-out demo from the barber.js site.
The markup of test page one is as follows:
<body style="background-color: red; color: white;" data-barba="wrapper" data-barba="page1">
<h3>Constant</h3>
<main data-barba="container" data-barba-namespace="home">
<h1>Page 1</h1>
go to page 2
</main>
The markup of test page 2 is as follows:
<body style="background-color: white; color: red;" data-barba="page2">
<h3>Constant</h3>
<main data-barba="container" data-barba-namespace="home">
<h1>Page 2</h1>
go to page 1
</main>
With the following JS at each the bottom of each page:
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.3.4/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#barba/core"></script>
<script>
barba.init({
//sync: true,
transitions: [{
name: 'opacity-transition',
leave(data) {
return gsap.to(data.current.container, {
opacity: 0
});
},
enter(data) {
return gsap.from(data.next.container, {
opacity: 0
});
}
}]
});
</script>
When leaving the current page the old element fades out OK, however the new element appears underneath a fraction early meaning I have two elements the new one jumping up as the old finishes disappearing?
Is there a way for the new one only to start appearing after the old one has finished?
I agree, the basic example is kinda failed. It turns out it depends on the styles a bit.
I managed to make it work adding display: 'none' to the leave transition, that forces the previous container to disappear before the next starts displaying:
// ...
leave(data) {
return gsap.to(data.current.container, {
opacity: 0,
display: 'none',
});
}
// ...
My best guess: the transition is meant to allow container overlapping. So you could get away with css (position: relative or something like that).

pressKey Enter on contenteditable in Safari

I'm trying to use TestCafe to test a chatbot which uses a contenteditable div as the user-input. Have actually succeeded with Chrome and Firefox to press enter and pass the tests, but have not been able to get Safari to press enter. I realize that contenteditable does not support pressKey("enter") but I'm wondering why it works for both Chrome and Firefox and not Safari, and whether I can get it to work for Safari?
test("Able to send a message on enter keypress", async t => {
await t
.typeText(chatbot.userReply, "hi")
.pressKey("enter")
.expect(chatbot.transcriptMessages.find("li").withText("hi").count).eql(1)
})
It's difficult to say why this does not work in Safari without researching a working sample showing the problem. As far as I understand from your description, your contenteditable element has the keypress event handler, which sends a message on the enter press. I've prepared a sample project to demonstrate this approach, and it all operates correctly both Safari and Chrome:
Test page:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="editor" contenteditable="true" style="width: 300px; height: 300px; border: 1px solid black;">test</div>
<script>
document.getElementById('editor').addEventListener('keypress', function() { alert('test') })
</script>
</body>
</html>
Test code:
fixture `test`
.page `../pages/index.html`;
test(`test`, async t => {
await t.click('#editor');
await t.pressKey('enter');
});
In a comment on this page you mentioned that this is in an iframe so you will need to do:
await t.switchToIframe(iframeSelector);
When switching back you can do:
await t.switchToMainWindow();

Check if everything (including video) is loaded in Vue?

I have a Vue project that is getting a little large due to an embedded html5 video and am wondering how to tackle the loading issue for this site.
Is there a way to know if everything is loaded in Vue so I can show a loading screen before everything is ready? And does this loading take into account of assets loading like images, videos, etc?
If you want to wait for the rest of the webpage to finish loading before displaying the video, you can wait until the window has loaded (load event) and then display the video via v-if.
Here's some additional things to consider (you're using webpack, right?):
Code splitting
If your JS bundle is getting too big, you can split it into smaller chunks and the webpack runtime will download the chunks asynchronously on demand.
I like to split my vendor code into a separate chunk, as well as split off some router components like this:
{
path: 'foo',
component: () => import('./components/foo.vue'),
}
See Code Splitting (Webpack docs) and Async Components (Vue docs) for more info.
Loading page
Your webpage will initially appear blank while the browser is downloading the HTML and JS assets before the Vue app has been bootstrapped. During this time, you can display whatever plain HTML content you want, then mount the root Vue component over the loading HTML.
const App = {
template: '<div>My App</div>',
};
function bootstrap() {
new Vue({
el: '#app',
render: h => h(App),
});
}
// Simulate loading
setTimeout(bootstrap, 2000);
body {
font-family: sans-serif;
}
#keyframes loading-anim {
from { opacity: 1; }
to { opacity: 0.3; }
}
.loading {
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
font-size: 40px;
color: #888;
letter-spacing: -0.05em;
font-weight: bold;
animation: loading-anim 1s ease-in-out alternate infinite;
}
<div id="app">
<!-- Put whatever loading HTML content here -->
<div class="loading">LOADING</div>
</div>
<script src="https://rawgit.com/vuejs/vue/dev/dist/vue.js"></script>

ASP.NET MVC 4 Default template has a different syntax for logout in _LoginPartial.cshtml

I am using ASP.NET MVC 4 for the first time, so I started with the default template.
In the _LoginPartial.cshmtl for Log off link I found the below code
#using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm" })) {
#Html.AntiForgeryToken()
Log off
}
I was expecting a code like the one below, which I have been using in MVC 3.
#Html.ActionLink("Log off", "LogOff", "Account")
Please can someone help me understand as to why this is necessary, and its advantages if any. Thanks
The reason for the new syntax is that it follows a more RESTful syntax. By logging out you are changing a state on the user (hence the POST action).
While making MVC 4 restful, the default template doesn't allow users with JavaScript disabled a way to log out. Here is the fix for that problem.
Note I also blogged about this issue here: http://www.shiningtreasures.com/post/2013/08/09/cannot-log-out-of-aspnet-mvc4-without-javascript
#using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm" })) {
#Html.AntiForgeryToken()
<a id="logout" href="javascript:document.getElementById('logoutForm').submit()" style="display:none">Log Off</a>
<script>
//<!--
var l = document.getElementById('logout');
if (typeof(l) != 'undefined' && l != null)
l.style.display = "inline";
//-->
</script>
<noscript>
<input type="submit" value="Log Off" />
</noscript>
}
Basically, it falls back to a submit button rather than a link when JavaScript is not available. We still use a POST in all cases.
One other small problem - the CSS for the template makes the button look different than a link. Here is the fix for the CSS to style the logout button so it looks the same as the other "buttons" that are actually anchor tags.
/* drop this in just above "info and errors" */
#logoutForm input[type="submit"],
#logoutForm input[type="button"],
#logoutForm button
{
background-color: #d3dce0;
color: #333;
border: none;
border: 0px;
font-size: 1em;
font-weight: 400;
margin: -4px 3px -4px 10px;
padding: 2px 3px;
text-decoration: none;
font-family: inherit;
outline: medium none;
}
/* for mobile styles - you need to drop this one in right after the other
#login styles in the mobile block (near the bottom of the file) */
#login input[type="submit"],
#login input[type="button"],
#login button
{
background: none;
color: #999;
border: none;
border: 0px;
font-size: 1em;
font-weight: 600;
margin: -4px 3px -4px 6px;
padding: 0;
text-decoration: none;
font-family: inherit;
outline: medium none;
}
There's no big difference. MVC4 uses a HTML-form to logout, which is submitted via the javascript.
The advantage is that the new way (with the form) uses javascript to submit the form, which is why the page does not have to reload.
I'm pretty sure the only reason they used JavaScript here is because the css style of a submit button wouldn't have matched the css style of the "login" button which is an anchor tag created by the HTML helper with this code:
#Html.ActionLink("Log in", "Login", "Account", routeValues: null, htmlAttributes: new { id = "loginLink" }).
The following will create the exact same behavior in the app:
<input type="submit" value="Log Off" />
but it looks horrible.
Of course they can't use the HTML helper ActionLink for the log off button anymore because this is a form that needs to be POSTed so that the AntiForgeryToken can be validated.
So, they needed the following:
An anchor tag for the log off link so that it will style the same as the log in link.
A button that can submit the form so that the AntiForgeryToken can be validated.
Hench an anchor tag that triggers a form postback via the explicit .submit() JavaScript.
"The advantage is that the new way (with the form) uses javascript to submit the form, which is why the page does not have to reload" ... (user1797792)
This is completely untrue as Html.BeginForm always triggers postback, Ajax.BeginForm is the async form helper that does not trigger post back
I prefer the old action link style as does not mess up css but from reviewing the function, it appears the actionlink has been replaced with form so that a AntiForgeryToken can be included in the request and would prevent cross site scripting blocking you out of your own account or something along those lines.
function btnContinueClick() {
debugger
$.ajax({
url: '#Url.Action("BIAssessmentTest", "BI")',
type: 'Post',
cache: false,
success: function (data) {
window.location.href = '#Url.Action("BIAssessQuestions", "BI")';
},
error: function (err) {
debugger
alert("hi");
}
});
}