How to get the computed value of a CSS variable in Playwright? - playwright

I'm trying to use Playwright to test an Ionic React app.
Ionic makes extensive use of CSS variables.
My app allows users to change some of these colors, so I want to verify the color changes work properly.
I am trying to find a way to test the value of the CSS variable.
The Ionic CSS looks like this:
ion-header ion-toolbar {
--background: var(--ion-color-secondary);
}
How can I get the value of --background with Playwright?

This GitHub comment describes how to use getPropertyValue() to get the value of a CSS property. This will also return the computed result for CSS variables:
const navBar = await page.locator('ion-header ion-toolbar >> visible=true');
const color = await navBar.evaluate((element) =>
window.getComputedStyle(element).getPropertyValue('--background'),
);

Related

Export NextJS project as a module

I'm looking for a little guidance and suggestions here. My attempts and theories will be at the bottom.
I have a NextJS project from which I want to export the top level component (essentially the entry file) so that I can use it as a preview in my dashboard.
The nextjs project is very simple. For the sake of simplicity, let's imagine that all it renders is a colored <h1>Hello world</h1>. Then in my dashboard, I want to render a cellphone with my NextJS component embedded and then from the dashboard change the color of the text, as a way to preview how it would look like. I hope this makes sense.
I'm lost at how I could export this component from NextJS and import it into my dashboard. The dashboard is rendered in Ruby on Rails. It would be simple enough to just import the repo from git and access the file directly form node_modules, but I'm looking for a solution that doesn't require installing npm on our Rails project.
Paths I have thought about:
1 - Install npm on Rails and just import the source code from NextJS repo and access the file and render with react (Simple, but we're looking for a non-npm solution)
2 - Bundle the component with webpack and load it directly into rails (does this even work?) - I exported the js and all it did was freeze everything :P Still trying this path for now
3 - Using an iframe and just accessing the page (then I can't pass any callbacks into the iframe to change the color directly from the dashboard)
4 - I cannot separate this component from NextJS to use as a library in both repos. The component we are exporting is the "ENTIRE" NextJS app jsx and it wouldn't make sense to separate in a different repo
Does anyone have a suggestion on how I could achieve this?
I think you could use an iframe with the nextjs app url. Then if you want to change the color, simply add the color in query parameter of the iframe and handle it on nextjs app.
Simple example
Rails view (erb)
<iframe src="#{#nextjs_url}?color=#{#color}" />
NextJS
# do something to get the query param of the page and and set to prop of the component
const YourComponent = ({color}) => {
return <h1 style={{color}}>Lorem</h1>;
}
While trying Hoang's solution, I decided to dive deeper into how to communicate with an iframe and the solution actually feels quite good.
You can set up listeners on either side and post messages in between the projects.
So in my dashboard:
function handleEvent(e) {
const data = JSON.parse(e.data)
if (data.type === "card_click") {
//if type is what we want from this event, handle it
}
}
// Setup a listener with a handler
// This will run every time a message is posted from my app
window.addEventListener("message", handleEvent, false)
const postMessage = (color) => {
const event = JSON.stringify({
type: "color_update",
color,
})
// Find the iframe and post a message to it
// This will be picked up by the listener on the other side
document.getElementById("my-iframe-id").contentWindow.postMessage(event, "*")
}
And on my app:
function handleEvent(e) {
const data = JSON.parse(e.data)
if (data.type === "color_update") {
// Do whatever is necessary with the data
}
}
// Setup listener
// This will fire with every message posted from my dashboard
window.addEventListener("message", handleEvent, false)
const handleCardClick = (cardIndex) => {
const event = JSON.stringify({
type: "card_click",
cardIndex,
})
// post message to parent, that will be picked up by listener
// on the other side
window.parent.postMessage(event, "*")
}
It feels pretty straight forward to communicate with an iframe with this solution.

How to disable font scaling in React Native for IOS app?

Enlargement of size of the device font will sometimes break (Styling wise).
Disabling font scaling can hurt the accessibility of your app, ideally if you want to limit scaling for Apps using React native 0.58.0 and above; use the maxFontSizeMultiplier prop on specific Text components.
However if you absolutely want to disable font scaling across your entire Application, you can do so by globally setting the allowFontScaling prop in the defaultProps of Text.
You should place these lines in your root entrypoint (normally index.js) before AppRegistry.registerComponent.
For React Native 0.56.0+
Text.defaultProps = Text.defaultProps || {};
Text.defaultProps.allowFontScaling = false;
For earlier versions of React Native you should only need the second line, but having both won't hurt. The first line just protects against the Text component not having defaultProps which is the case for React Native 0.56.0 and above.
Add the above lines in the entry point file of your React Native application (usually index.js, app.js or main.js) to apply this prop to all Text components in your application.
This prop will only affect Text components and you may want to apply the same changes to TextInput which can be done with a similar snippet:
TextInput.defaultProps = TextInput.defaultProps || {};
TextInput.defaultProps.allowFontScaling = false;
Also note that some components wont obey font scaling settings, for example: Alert, PickerIOS, DatePickerIOS, TabBarIOS, SegmentedControlIOS as these are all natively drawn and don't rely on the Text component.
For React native 0.58+
Preferable to keep font scaling but you can limit it by using Text new prop maxFontSizeMultiplier
For React native 0.56+ use Levi's answer
Text.defaultProps = Text.defaultProps || {};
Text.defaultProps.allowFontScaling = false;
For React native 0.55 and lower
Add Text.defaultProps.allowFontScaling=false at the beginning of the app (e.g. main.js or app.js etc ...) to apply this prop on all Text components through out the whole app.
When user increase full font size from setting
Enlargement of size of the device font will not break (Styling wise).
index.js file
import {AppRegistry} from 'react-native';
import App from './src/App';
import {name as appName} from './app.json';
import {Text, TextInput} from 'react-native';
AppRegistry.registerComponent(appName, () => App);
//ADD this
if (Text.defaultProps == null) {
Text.defaultProps = {};
Text.defaultProps.allowFontScaling = false;
}
if (TextInput.defaultProps == null) {
TextInput.defaultProps = {};
TextInput.defaultProps.allowFontScaling = false;
}
<CalendarStrip
shouldAllowFontScaling={false}
/>
Also note that some components wont obey font scaling settings, for example: Alert, PickerIOS, DatePickerIOS, TabBarIOS, SegmentedControlIOS as these are all natively drawn and don't rely on the Text component.
if (Text.defaultProps == null) {
Text.defaultProps = {};
Text.defaultProps.allowFontScaling = false;
}
I kept this piece of code inside the constructor of index.js.It really worked well. By the I am using react native version 0.59.9 FYI.
Create an <AppText> component and use it with your presets instead of the original one, with your own default, including font scaling false. This is better because you can enrich it with your own API.
For example, my AppText permit to do things like:
<AppText id="some.translation.key" color="primary" size="l" underline italic bold/>
In another file, import the actual Text component as ScaledText so as a backup, and then redefine Text, overriding the allowFontScaling prop.
export function Text(props) {
return <ScaledText {...props} allowFontScaling={false} />;
}
Then, import your locally defined Text component, instead of the built-in React Native Text. This is also useful if you want to elegantly disable font scaling on only certain parts of your app.
For webview we can use textZoom={100} props to handle font-size change if font size is changed from mobile setting.
if imported from react-native-webview
<WebView
textZoom={100}
source={}/>
I'm kinda late, but if anyone wants a answer with Typescript, here it is
interface TextWithDefaultProps extends Text {
defaultProps?: { allowFontScaling?: boolean };
}
(Text as unknown as TextWithDefaultProps).defaultProps = {
...((Text as unknown as TextWithDefaultProps).defaultProps || {}),
allowFontScaling: false,
};

PointerLock with dart

Is there a way to lock the cursor with dart that works on Firefox and Chrome?
I tried:
void lock(event)
{
var canvas = document.querySelector('canvas');
canvas.requestPointerLock();
}
in a mousedown-event listener
document.addEventListener('mousedown', lock, false);
I also tried
renderer.canvas.requestPointerLock();
where renderer is a WebGLRenderer from the three.dart package.
The problem is this works only in Chromium.
I looked up the following crossbrowser-solution for js, but this doesn't work in dart.
canvas.requestPointerLock = canvas.requestPointerLock ||
canvas.mozRequestPointerLock ||
canvas.webkitRequestPointerLock;
Is there a way to do the pointer lock in dart, or do I need to find a way to execute the javascript above from dart?
There is an open issue for this https://dartbug.com/4463
I think the problem in your code code using prefixes is that canvas.requestPointerLock, canvas.mozRequestPointerLock, canvas.webkitRequestPointerLock don't return false if they don't exist (or true if it does). You have to get the current browser by other means and then call the prefixed method.

How would you auto format hyperlinks using meteor

I am working on a chat room application and would like to auto format hyperlinks so they can be visited without copy/paste.
I found autolink.js and was able to get it to work using a static HTML template but have not been able to get it working with meteor.
Any suggestions?
Edit -
Meteor Version 0.6.1
Chatroom Application - https://github.com/SmashBrando/chatroom
Autolink.js - https://github.com/bryanwoods/autolink-js
(this is not setup as it did not work)
Put this in the helper you want to display the hyperlink. Assuming you've got the autolink.js all set up in your /client/lib folder just use it with your helper
e.g
client js
Template.hello.greeting = function() {
return "This is a link to Google http://google.com".autoLink()
}
and you need to make sure your HTML uses handlebars that can give html output (thats with 3 curly braces either side instead of 2):
html in your template
{{{greeting}}}
This should output
This is a link to Google http://google.com
Using transform to autolink on cursors
When using a handlebars helper that returns a cursor such as Messages.find() in your code you need to transform your collection. So with your code you need to alter the return value:
Template.messages.messages = function () {
return Messages.find({}, { sort: {time: -1}, transform: function(doc) {
if(doc.message) doc.message = doc.message.autoLink()
return doc;
}
});
};
A transform changes the documents in your collection, so in the above each one's message is autoLinked.
You also need to let let handlebars display this as clickable links by altering your handlebars for the HTML to use 3 curly braces to make sure your 's aren't escaped.:
<template name="message">
<p><strong>{{name}}:</strong> {{{message}}}</p>
</template>

get src url parameter from script tag with selenium ide

I am using Selenium IDE to verify some elements on a page during a test. I have a script tag that has a dynamic SRC attribute on it. It generates the parameters for the url based on what page design i am on. I am trying to store the value of the parameters for this SRC attribute in Selenium IDE and can't figure out how to do it. Thoughts??
Here is the whole script tag. I just want the Selenium IDE to store the DesignFamily value.
<script src="/JS.aspx?DesignFamily=GSMFamily&Design=GSMExtreme&Version=2011-4-29-17-2-5" type="text/javascript"></script>
This might be the easy workaround. First create user-extension as given here
Then in user-extensions.js add this function.
Selenium.prototype.doStoreQueryStringParameter = function(xpath, varName) {
var currentDocument = selenium.browserbot.getCurrentWindow().document
var result = currentDocument.evaluate(xpath, currentDocument, null, XPathResult.STRING_TYPE, null);
result = result.stringValue
var str = result.split(";")[0].split("=")[1];
storedVars[varName] = str;
};
storeQueryStringParameter function should be in command dropdown after your user-extensions.js has been loaded.
While using this your target should be something like //*parent tags to script*/script[n]/#src //n =1,2,3.. e.g select 2 if 2nd script inside of its of parent tag is to be used
This may not be the most graceful solution, but you can explore the use of getHtmlSource() available in the IDE...
Though, without extending the capability using RC, I'm not sure about parsing the needed information.

Resources