I realise this is a non-trivial task, but is there a way to regression test the styling and rendered layout of a web application?
I've found it straightforward to unit test and regression test functionality, both server-side and client-side.
However, a frustrating issue I've run into are CSS changes made to fix one layout issue that break the layout and styling on a different page. The only way I know how to detect these is to manually view every page in an application, and compare it with my own expectations, but obviously this can be burdensome and expensive when an application can have dozens of pages. Has there been any research using image processing or other techniques to detect these kinds of problems automatically?
Actually, one of the hidden gems of Selenium is that you can use it to take screen captures of the browser. Then using a technique as described in Find differences between images using C#, you can highlight the differences between previous snapshots.
This example shows how to grab a screenshot of the homepage and then create a difference image. With a little extra tinkering, you can use the same technique to count the pixels that are different.
[Test]
public void CompareHomePageToPrevious()
{
string fileName = Path.Combine(Environment.CurrentDirectory, "homepage.bmp");
var selenium = new DefaultSelenium("localhost", 4444, "*chrome", "http://mywebsite");
selenium.Start();
selenium.Open("/");
selenium.CaptureEntirePageScreenshot(fileName, "");
// Load current and previous captures
var current = new Bitmap(filename);
var previous = new Bitmap(_previousHomepageImage);
// Find all pixels that are the same and make them pink
Bitmap diff = ImageTool.GetDifferenceImage(current,previous,Color.Pink);
diff.MakeTransparent(Color.Pink);
// Save the image for viewing
// or count the number of different
}
Selenium is a really interesting choice because it's cross-platform and cross-browser, meaning that you can capture screens of different browsers. You can use this technique to compare snapshots between builds or to compare between browsers.
There is a way to test the layout of a web application using Galen Framework. This tool has its own language and is very easy to learn and understand. It is a Selenium-based and you can run tests in Selenium Grid, (Sauce Labs) if you want to test your application in different browsers.
This tool gets the location of a specified element on the page and check them relatively to each other.
Example: if you want to check that a menu pane is below the header and stretches to the width of a browser and has 50 pixels height, you can do it like this:
menu
below: header 5px
width: 100% of screen/width
height: 50px
This tool can also be used to test responsive designs.
You can find complete documentation on the official website, http://galenframework.com.
The best part is you can even create Java tests. The Galen JavaScript API is also available along with the sample projects on GitHub.
Again, test(s) written once can be used at multiple phases of the application life cycle.
I guess you could generate an 'ideal' shot of each page in your web application to use as reference.
Then generate a new shot of every page after a CSS update and compare with the previous ones. A 1:1 comparison should be okay if you make sure you always keep the same resolution, etc.
You could even make it so that you can tell it that if the page differs, the other page is actually 'better' than the example and to use the 'other' as the example for the next runs.
That way, when you fix something you can see the difference for one page, and mark it as being better, and then fix a bug on another page while making sure you don't regress the bug you were trying to fix in the first place.
You should check out Web Consistency Testing as an approach to do your regression testing.
If you're developing in Ruby, take a look at the rspec-page-regression gem. It's an RSpec plugin that lets you compare requested page snapshots against an expected image. It works with Poltergeist, which is a Capybara driver that uses PhantomJS and supports rendering page snapshots.
Rspec-page-regression provides an RSPec matcher that lets you do things like
context "user page" do
before(:each) do
visit user_path
end
it { page.should match_expected }
context "popup help" do
before(:each) do
click_button "Help"
end
it { page.should match_expected }
end
end
And it provides a mechanism to manage the expectation images.
Disclaimer: I'm the author of the gem.
Related
I have a single page using CSS columns that reflows on load.
Even when I remove all IMGs and iFrames, so it is fetching no
external resources, it reflows.
I can't figure out what is causing the reflow/repaint. Any CSS exports
out there able to figure this one out?
https://github.com/treenotation/dumbdown/issues/8
There's too much content in document.
The browser will gradually display the content, that is, the content involved in rendering will gradually increase, which affects the layout calculation.
You can add the "loading state" style. When window.onload Event trigger, change the style to "load complete".
Or 'Masonry Layout'.
Reason for the reflow is: a huge amount of content but NO strategy to handle with. Indeed there are many things you can avoid/do/change ...
REASON WHY - just to base the answer ...
The reflow is caused by the mechanic: at first the text (html code) has been downloaded and rendered. But there are still a lot of elements (most over images but youtube videos and iframes as well) which are still on download. As the browser don't know the size of that elements he does not keep the place for that elements.
Now: after the download and rendering of every element has finished the browser injects the element to the content and all off the following content is pushed down and in your case to next column ... reflow.
STRATEGY: MULTIPLE ACTIONS
To your question: there is not only one reason which causes multiple and long downloads. So far there is no simple single answer and even NOT A SINGLE SOLUTION. Your needed strategy will be to optimize the page by a multiple bundle of actions. But I believe doing that you can reduce it to an acceptable amount ... and maybe there is a chance.
THINGS YOU CAN DO
1. Change layout
If you change the layout to an actual web technique. That means don't use columns (flowing left to right) to a style which prepares the pageflow from up to down. Than you can asynchron load the needed elements when the user scrolls down. The technique is named Infinite scrolling: How to do an infinite scroll in plain Javascript
But I assume as the special layout has charm this won't be an option for you!?
2. Images which are not shown - remove not needed elements from download
On your page I found images which are downloaded but which are not shown on the page. (Example: 3.png with INCREDIBILE USELESS 659KB). Remove such elements from your content.
3. Reduce not needed size of elements
Additional a lot of shown images on your page have an incredibly large file size which is not needed.
Example: devices.png
image-size: 692x285px - real size
layout-size: 287x118px - needed size
file-size-download: 110kb
file-size-needed: 4kb - if (lossless) optimized
And think about: many little file downloads add up to a big amount ... and you have a lot of downloads! If you calculate: 10 images your way: 1.1 MB can be done with 40KBs
Additional:
if you you need higher solutions use srcset attributes ...
sometimes that is a practical problem with the knowledge of the editors: than teach them how to lossless reduce images and advise them the sizes to use for the images in the layout
4. Use faster server for images
It seems the download rate from your server is not the fastest one. That's normal by most providers. As you have a lot of images ... think about to load images from a faster server - if possible. Example: the pure download service from AWS (Amazon Web Service) is incredibly fast. As you just need a bucket for downloading that is not as expensive ... try it out.
5. Use placeholders for elements
As you have a lot of elements I think you maybe cannot avoid the later injection which causes the reflow. But you can use placeholders for your element so the needed place is reserved and the reflow still does not happen for this element.
Just define the html structure and possible sizes in your layout. That additional helps the editors as they know what image size they can use. Then size the placeholders with CSS and initiate an ajax image download by JS.
In case of later download now the users maybe see a placeholder at the beginning but no reflow. You can do that with few lines of code. I attach an example at the end of the posting.
NOTE: You can do this with (youtube-)videos or iframes in a similar way ;-)
6. Use vanilla instead of jQuery
As I saw has the download of jQuery an incredible impact to your download time. Really. (That's the reason why I assume your server is a slower one.) Have a look to the download time of your elements. It is one of the elements which needs the most times and blocks your elements from rendering.
jQuery is an old dog. Modern web techniques use vanilla JS ... and as I see there are no complicated things on your page you cannot realize in vanilla. So the recommendation is to remove it from you page (if possible) and you will earn a huge speed advantage.
7. Use CDNs for download when possible
Downloading frameworks and fonts from own server makes pages slow and blocks time for the page download of other elements. Use a CDN instead.
As I have seen your fonts are loaded from a CDN? But jQuery still comes from your server. If you don't want to change to vanilla chose to load it from CDN.
8. Check if Youtube can be loaded more simple
Youtube is loaded by several actions to your page. In this case I AM NOT SURE as I still did not work with youtube for a longer time. But I believe (not sure if I am right) that there is a more direct way to include youtube videos to a page. Maybe you would like to check it.
But nevertheless: work with placeholders for the video players as well. That are almost just few additional lines off css.
9. Optimizing user experience: thinking about a preloader
Reflow is not new phenomenon to webpages. Up to now a lot of pages uses preloaders to generate a better user experience. Today's technique is ajax load...
I don't know if the described techniques will avoid the reflow completely. As there are many elements the download time cannot be set to zero. But optimizing the page will reduce it dramatically. If there still remains a little bit ... maybe you like to think about the older technique. Using a nice and maybe well designed preloader symbol indeed can upgrade the user experience. Maybe on mobile views with medium data speed there is no other chance...?
But that is just to think about an additional possibility ...
[update]
10. Combine placeholder with infinite scroll
If you are using placeholders you can/should combine it with technique infinite scroll.
Means: all media (particularly images but maybe videos and iframes as well) are prepositioned by sized placeholders. That works immediately so there should be no more reflow as needed. Then load media assynchron by AJAX based on their position on their screen. Images which are in view are loaded immediately.
As you don't have so many media elements on starting viewport (most are still below the screen view) that should work as if it is a page with a 'normal number' of pictures/medias.
All others are loading afterwards when scrolling the page the media comes in view like on a 'infinite scroll page'. (Note: that works if the file size off the images is not to large, - so optimizing the images has still to be done.)
That has the additional advantage that thake makes sure that the images are loaded in the sequence they are needed ... which safes a lot of time.
Could be done in javascript:
Place images/media by placeholder technique
On window.onload check which images/media are in the viewport. Don't forget images which are only partly seen.
On window.onscroll check if image(s) comes to viewport and load image
Note: I am not quite sure if there are anchor links on your page to the single articles. I believe not. But if you still use them the starting viewport can be anywhere on the page when the user call an article. In that case window.onscroll has not only to work scrolling down but scrolling up to.
I am not quite sure if there is a ready script avaiable. But I would wonder if not. Otherwise it would not be to tricky to do that on your own. That would have the charm that such scripts mostly have less and cleaner code than preworked scripts ...
[end update]
... ... ...
I am not quite sure if the described issues are complete. Mostly there are found more possibilities to optimize a page when you start with the process. But as I had a nearer look to your page that are the most important chances.
EXAMPLE LAZY IMAGE LOAD WITH PLACEHOLDER EFFECT
Just EASY AND SIMPLIFIED example for lazy image load. Please adapt to your need.
// new html for image
<img class="placeholder-size" src="path/placeholder.jpg" data-lazy-url="https://url-to-your/imag.png" alt="Image Description">
// css
.placeholder-size {
width: 200px;
height: 100px;
}
// js for lazy load
// older code but works, please actualize if needed
window.onload = function(){
var lazyImages = document.querySelectorAll('[data-lazy-url]');
for (var i in lazyImages) if (lazyImages.hasOwnProperty(i)) {
var imgUrl = lazyImages[i].getAttribute('data-lazy-url');
lazyImages[i].src=imgUrl;
};
};
The thing is I tried using https://baskren.github.io/Forms9Patch/ but I feel like I don't fully grasp it.
Don't get me wrong, the tool is great it does stretch the 9patch images. It's just that I can't get the buttons to look properly based of Google brand guidelines.
https://developers.google.com/identity/branding-guidelines
The way it should look
And this here are the drawables I am using :
https://developers.google.com/identity/images/signin-assets.zip.
Here are the results of different button tries and dimensions
This is the code that got me the closest to the button I want
<f9p:Button Text = "Sign in with xxhdpi"
TextColor="White"
FontSize="14"
FontFamily="sans-serif-medium"
WidthRequest="60"
>
<f9p:Button.BackgroundImage>
<f9p:Image Source="{local:ImageMultiResource TestingApp.Resources.Images.btn_google_signin_dark_normal_xxhdpi}"/>
</f9p:Button.BackgroundImage>
</f9p:Button>
I tried using a grid with image and button as well but it didn't work out.
It would be awesome if someone would point me in a proper direction.
I've actually done this before. Here is a general outline of what I did:
Put your multi-platform icon files into your .NetStandard project as Embedded Resources. This means that I found all of the various resolutions provided by Google (_xxhdpi, _xhdpi, _hdpi, _mdpi, etc) and then renamed them to the following:
icon#¾x.png
icon.png
icon#1½x.png
icon#2x.png
icon#3x.png
icon#4x.png
And then put them in to the Resources/Google folder in my project (FormsFirebase.Ui). So, for example, the EmbeddedResourceId for the first file, in the above list, is FormsFirebase.Ui.Resources.Google.icon#¾x.png.
As you will see in a moment, renaming these files, as shown above, will allow Forms9Patch.Button to pick the right image for the right screen resolution (so it will look great) - freeing you from having to manage this. Likewise, putting them in the .NetStandard project means they are available for all platforms - freeing you up from having to figure this out multiple times!
In your Forms9Patch.Button, refer to the above icon image in a resolution independent fashion. This can be done a couple of ways. One of the more verbose ways is:
var myButton = new Forms9Patch.Button
{
Text = "Sign in with xxhdpi",
TextColor=Color.White,
FontSize=14,
FontFamily="sans-serif",
WidthRequest=60,
IconImage = new Forms9Patch.Image
{
Source = Forms9Patch.ImageSource.FromMultiResource("FormsFirebase.Ui.Resources.Google.icon", GetType().Assembly),
Padding = 1,
},
Spacing = 4,
TintIcon = false,
BackgroundColor = Color.FromRGB(81,134,236)
};
A couple of things to Note:
First, I set TintIcon to false in order to not tint the icon to the same color as the TextColor. Also, I set IconImage, not BackgroundImage. This is to be sure the image is a peer to the text, rather than in a layer below it.
Also note that I am able to set the padding of the IconImage as well as the Forms9Patch.Button.Padding and the Forms9Patch.Button.Spacing (the distance between the IconImage and the Text or HtmlText, depending on if HasTightSpacing has been set to true).
Instead of using multiple .png files (for each screen resolution), if you have .svg version of your image available, you can use that instead. Much less work!
Another thing you might be interested in: Just as Forms9Patch handles images in a platform independent fashion (by putting them in a cross platform project as Embedded Resources), it can do the same thing with Fonts. This means you can put a font file (.ttf or .otf) into your cross platform project and use its EmbeddedResourceId as the value for FontFamily. And this behavior can be extended to Xamarin.Forms elements by use of the Forms9Patch.EmbeddedResourceFontEffect.
Now for a bit of proselytization (please forgive me if this does not apply to you): I see that you used XAML for your sample code. Notice I didn't in my response. If you are new to .Net and/or Xamarin.Forms, I would highly recommend not using XAML. Don't get me wrong, XAML is great - it's just not for beginners. Why? There's just too many things going on under the covers that, as a beginner, will trip you up and slow you down. Rather, I would recommend you write all of your UI in C# so you can learn to manage your properties and learn how binding really works. Once you have mastered making very efficient layouts with the best "context appropriate" use of binding, then you're ready for XAML. For me, the real test was being able to make very a complex cell layout in a large list in a ListView smoothly scroll on a low-end Android phone. After that experience, I was able to take advantage of all the benefits of developing in XAML (and there are many) without worrying about being shackled by my novice mistakes.
Is there a simple way to trigger a mobile OS's native pop-up/alert/etc. from some form of web code? I'm writing an ASP.NET mobile web page and I'd like to, for example, have the iPhone's UIAlertView appear.
EDIT: What I'm looking for is not the method with which to detect which mobile browser is accessing the site (I already know how to do that). If the code to trigger a pop-up that will look nice in an Android browser is different than the code to trigger a pop-up that will look nice in an iPhone browser, I can simply throw in a switch statement that redirects the user to the pop-up that corresponds with their browser. I'm trying to find the html/javascript/asp.net code which will create a mobile-friendly pop-up, either in general or for the various popular mobile web browsers specifically.
Don't know whether there is any pre-built functionality in .NET that can achieve this, but you can surely write one yourself.
You can write a method, that returns the code for your popup, based on the user OS (simple switch statement should do).
EDIT after taking a short nap:
I believe you should reconsider using popups. They are quite annoying even on desktop browsers and many people block them automatically. Probably every blog about accessibility will tell you, that you should keep mobile version of your website as simple as possible because of various compatibility issues that you can run into.
Instead, try to think about some interesting way to incorporate messages for users in a different and appealing way, that won't disturb anybody.
What I do is use a div popup (that floats ontop of the page) and eighter make a big close button or set at timeout to remove it.
jquery mobile is a good place to start.
I'm asking if you know if there is a ready-made solution, not really how to do it.
I'm quite sure I can pull it off myself, even if I never ever touched the bytes of a JPEG manually. If you'd like a crack on it, you're invited to do so ;)
The basic Idea is that you have a site with a few JPEG images, but you want to reduce load as much as possible for mobile users.
So you ensure that all of your JPEG´s are progressive and only sends the low-frequency bits of it first, idles down the TCP-connection, and waits for the client to report in how big the available space is in the browser window.
Or alternatively, you have some sort of browsercaps.ini or similar, and rely on that to get the initial resolution -- and then have the reporter report a correction if necessary.
I actually needs this for two entirely separate environments, one is using PHP and the other is using node.js (The latter one is of more importance).
I'm quite sure picasaweb is doing this stuff already, or at least did. You could view an image, and it loads progressively -- then you could enlarge it, it got blocky but continued to load in progressively, I remember that I was quite impressed by that!
(And its unfair that Google keep the cool stuff for them selves, remember their motto {°«°] )
Why not send the client a list of images that could be used for a specific img tag, then have the client determine which one it should use?
It is possible to determine the screen size of the device document.write(screen.width+'x'+screen.height);or the size of the browser. And instead of adding a src attribute for each image, adding the possible sources to a html5 data- attribute like so:
<img data-img="mobile:some-img.jpg,desktop:other-img.jpg" />
JavaScript (With jQuery):
$('img').each(function(){
$(this).attr('src', $(this).attr('data-img').split(',')[0].split(':')[1]);
});
I'm generating a coupon based on dynamic input and a cropped image, and I'm displaying the coupon using ntml and css right now, the problem is, printing this has become an issue because of how backgrounds disappear when printing and other problems, so I think the best solution would be to be able to generate an image based on the html, or set up some kind of template that takes in strings and an image, and generates an image using the image fed in as a background and puts the coupon information on top.
Is there anything that does this already?
This is for an ASP.NET 3.5 C# website!
Thanks in advance.
edit: It'd be great if the output could be based on the HTML input, as the coupon is designed by manipulating the DOM using jQuery and dragging stuff around, it all works fine, it's just when it comes to the printing (to paper) it has z-indexing issues.
What you can do is create an aspx page that changes the response type to be in the format you want and then put the image into the stream. I created a barcode generator that does a similar thing. Excluding all the formalities of generating the image, you'll Page_Load will look something like this:
Bitmap FinalBitmap = new Bitmap();
MemoryStream msStream = new MemoryStream();
strInputParameter == Request.Params("MagicParm").ToString()
// Magic code goes here to generate your bitmap image.
FinalBitmap.Save(msStream, ImageFormat.Png);
Response.Clear();
Response.ContentType = "image/png";
msStream.WriteTo(Response.OutputStream);
if ((FinalBitmap != null)) FinalBitmap.Dispose();
and that's it! Then all you have to do in your image is set the URL to be something like RenderImage.aspx?MagicParm=WooHoo or whatever you need. That way you can have it render whatever you want to specify.
You can render html to a bitmap using the WebBrowser control in either a winforms or console application.
An example of this can be found here: http://www.wincustomize.com/articles.aspx?aid=136426&c=1
The above example can be modified to run in ASP.Net by creating a new STAThread and performing an Application.Run on it to start a new message loop.
PHP/Ruby Alternative
If you have accessed this question and are actually looking for soething that will work without Windows, you can try the KHTML library: http://wiki.goatpr0n.de/projects/khtmld
The website has a ridiculous name I admit, but I can assure you it is genuine. Other related pages are: the sourceforge page http://khtml2png.sourceforge.net/
Try PDFSharp...it's not exactly a "take this HTML and make a PDF" but with a small amout of fiddling you can easily make a PDF out of the info you are using to make the HTML.
MARKUP ONLY ALTERNATE SOLUTION
Use SVG and XSLT to transform the html data into an image that can be rendered/saved/etc.
I'll admit that at first it was tedious getting this to work because of all of the coordinates, but well worth the effort once it is running.
There is a very powerful image creation library called GD which I often use with PHP.
I am led to believe there is a wrapper for this library that ASP programmers can use. Try this
Unless the "other problems" are pretty severe, couldn't you just instruct your users to turn on Background Images when printing?
In any case, I'd default to serving a PDF rather than an image, doubly so since it is intended for print.
Just set up your css properly, so that you have a css file targeted at the print medium. It is pretty easy to guarantee that the coupon will always be legible, without worrying about whether they have bg images on or not. Needlesly moving to an image doesn't make any sense, unless there is some reason you don't want it to be machine readable.
I haven't tried to myself, but you should be able to render HTML into an image by using the WebBrowser control and the DrawToBitmap() method inherited from the base Control class.
UPDATE: I tried this myself and there are some caveats. The WebBrowser control doesn't seem to render the web page until the control is show, so the WebBrowser needs to be in a Form and the Form must be shown for the HTML to be rendered and the DocumentCompleted event to be raised.