I am new to AngularJS. I'm trying to run end-to-end tests with Protractor. Currently, I am running my tests from grunt with help from grunt-protractor-runner. My base test looks like the following:
describe('My Tests', function () {
var p = protractor.getInstance();
beforeEach(function () {
});
it('My First Test', function () {
var message = "Hello!";
expect(message).toEqual('Hello!');
});
});
This works just fine. However, it really doesn't test my app. To do that I always want to start in the root of the app. In an attempt to do this, I've updated the above to the following:
describe('My Tests', function () {
var p = protractor.getInstance();
beforeEach(function () {
p.get('#/');
});
it('My First Test', function () {
var message = "Hello!";
expect(message).toEqual('Hello!');
});
});
When this test gets ran, Chrome launches. However, "about:blank" is what gets loaded in the address bar. My app never loads. I've reviewed my protractor.config.js file and it looks correct. It looks like the following:
exports.config = {
allScriptsTimeout: 110000,
seleniumServerJar: './node_modules/protractor/bin/selenium/selenium-server-standalone-2.37.0.jar',
seleniumPort: 1234,
seleniumArgs: [],
seleniumAddress: null,
chromeDriver: './node_modules/protractor/bin/selenium/chromedriver.exe',
capabilities: { 'browserName': 'chrome' },
specs: [ '../tests/**/*.spec.js' ],
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000
}
};
How do I get my app to load into Chrome for the purpose of an integration test via protractor?
Perhaps you've already figured out how to get it working, but if not maybe the following will help (modify the port if necessary of course):
// A base URL for your application under test. Calls to protractor.get()
// with relative paths will be prepended with this.
baseUrl: 'http://localhost:3000'
Add this property to your protractor.config.js file.
Reference: https://github.com/angular/protractor/blob/master/referenceConf.js
Related
beautiful people on the internet. I am new to chrome extension not new to writing code though. I have implemented webpack to use external packages. One major one in my application is npm package by the name "mark.js".
My application works like this i want some specific words to be highlighted in active webpage using this package. I have written code for this to achieve the functionality but the problem is with loading the script in a web page. I have performed different aspect of loading script but that doesnot work. The new MV3 version have some strict rules.
I want to achieve anything similar of loading script in an active webpage. Please help.
btn.addEventListener("click", async () => {
console.log("BUTTON IS PRESSED!!");
try {
await chrome.tabs.query(
{ active: true, currentWindow: true },
async function (tabs) {
chrome.scripting.executeScript({
target: { tabId: tabs[0].id },
func: highlightText,
args: [arr],
});
}
);
} catch (e) {
console.log("ERROR AT CHROME TAB QUERY : ", e);
}
});
async function highlightText(arr) {
console.log(typeof Mark);
try {
var instance2 = new Mark(document.querySelector("body"));
// instance2.mark("is");
var success = [];
// const instance2 = new Mark(document.querySelector("body"));
await Promise.all(
arr.map(async function (obj) {
console.log("OBJECT TEXT : ", obj.text);
instance2.mark(obj.text, {
element: "span",
each: function (ele) {
console.log("STYLING : ");
ele.setAttribute("style", `background-color: ${obj.color};`);
if (obj.title && obj.title != "") {
ele.setAttribute("title", obj.title);
}
ele.innerHTML = obj.text;
success.push({
status: "Success",
text: obj.text,
});
},
});
})
);
console.log("SUCCESS : ", success);
} catch (error) {
console.log(error);
}
}
There's no need to use chrome.runtime.getURL. Since you use executeScript to run your code all you need is to inject mark.js before injecting the function.
Also, don't load popup.js in content_scripts, it's not a content script (these run in web pages), it's a script for your extension page. Actually, you don't need content_scripts at all.
btn.addEventListener('click', async () => {
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
const target = { tabId: tab.id };
const exec = v => (await chrome.scripting.executeScript({ target, ...v }))[0].result;
if (!await exec({ func: () => !!window.Mark })) {
await exec({files: ['mark.js.min'] });
await exec({func: highlightText, args: [arr] });
}
});
For V3 I assume you will want to use Content Scripts in your manifest to inject the javascript into every webpage it matches. I recently open-sourced TorpedoRead and had to do both V2 and V3, I recommend checking the repo as it sounds like I did something similar to you (Firefox is V2, Chrome is V3).
The code below need to be added to your manifest.json and this will execute on every page based on the matches property. You can read more about content scripts here: https://developer.chrome.com/docs/extensions/mv3/content_scripts/
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["yourscript.js"]
}
],
I need to pass the connection argument while calling lighthouse
https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/index.js#L41
async function lighthouse(url, flags = {}, configJSON, connection) {
// verify the url is valid and that protocol is allowed
if (url && (!URL.isValid(url) || !URL.isProtocolAllowed(url))) {
throw new LHError(LHError.errors.INVALID_URL);
}
// set logging preferences, assume quiet
flags.logLevel = flags.logLevel || 'error';
log.setLevel(flags.logLevel);
const config = generateConfig(configJSON, flags);
connection = connection || new ChromeProtocol(flags.port, flags.hostname);
// kick off a lighthouse run
return Runner.run(connection, {url, config});
}
And in my testcafe my tests look like
test('Run lighthouse, async t => {
lighthouse('https://www.youtube.com', {}, {}, ????)
})
I am unable to retrieve the connection of the chrome instance that testcafe had opened up, instead of spawning a new chromeRunner
there is an npm library called testcafe-lighthouse which helps to audit web pages using TestCafe. It also has the capability to produce an HTML detailed report.
Install the plugin by:
$ yarn add -D testcafe-lighthouse
# or
$ npm install --save-dev testcafe-lighthouse
Audit with default threshold
import { testcafeLighthouseAudit } from 'testcafe-lighthouse';
fixture(`Audit Test`).page('http://localhost:3000/login');
test('user performs lighthouse audit', async () => {
const currentURL = await t.eval(() => document.documentURI);
await testcafeLighthouseAudit({
url: currentURL,
cdpPort: 9222,
});
});
Audit with custom Thresold:
import { testcafeLighthouseAudit } from 'testcafe-lighthouse';
fixture(`Audit Test`).page('http://localhost:3000/login');
test('user page performance with specific thresholds', async () => {
const currentURL = await t.eval(() => document.documentURI);
await testcafeLighthouseAudit({
url: currentURL,
thresholds: {
performance: 50,
accessibility: 50,
'best-practices': 50,
seo: 50,
pwa: 50,
},
cdpPort: 9222,
});
});
you need to kick start the test like below:
# headless mode, preferable for CI
npx testcafe chrome:headless:cdpPort=9222 test.js
# non headless mode
npx testcafe chrome:emulation:cdpPort=9222 test.js
I hope it will help your automation journey.
I did something similar, I launch ligthouse with google chrome on a specific port using CLI
npm run testcafe -- chrome:headless:cdpPort=1234
Then I make the lighthouse function to get port as an argument
export default async function lighthouseAudit(url, browser_port){
let result = await lighthouse(url, {
port: browser_port, // Google Chrome port Number
output: 'json',
logLevel: 'info',
});
return result;
};
Then you can simply run the audit like
test(`Generate Light House Result `, async t => {
auditResult = await lighthouseAudit('https://www.youtube.com',1234);
});
Hopefully It helps
I hope you can help me with my problem.
Currently I build a PWA with a service-worker. It registerd successful, but something is wrong with the installation.
The "caches.open"-promise result in an error: "TypeError: Request failed at ". You can see in Chrome, that the cache is registerd, but empty.
I already checked the cache urls thousand times..
Here is my Service-worker Code
var CACHE_NAME = 'surv-cache-1';
var resourcesToCache = [
'/',
'/index.html',
'/jquery-3.2.1.min.js',
'/pouchdb.min-6.4.1.js',
'/styles/inline.css',
'/scripts/app.js'
];
self.addEventListener('install', function(event) {
event.waitUntil(
// open the app browser cache
caches.open(CACHE_NAME).then(function(cache) {
console.log("Install succesfull");
// add all app assets to the cache
return cache.addAll(resourcesToCache);
}).then(function(out){
console.log(out);
}).catch(function(err){
console.log(err);
})
);
});
self.addEventListener('fetch', function(event) {
event.respondWith(
// try to find corresponding response in the cache
caches.match(event.request)
.then(function(response) {
if (response) {
// cache hit: return cached result
return response;
}
// not found: fetch resource from the server
return fetch(event.request);
}).catch(function(err){
console.log(err);
})
);
});
And my registration code:
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('service-worker.js').then(function(registration) {
console.log('Service worker registered:'+registration.scope);
}).catch(function(e) {
console.log(e);
});
};
I didn't get it.. I hope you have an idea :)
EDIT: I think I know now why it don't work. I have a authentication for my domain, so not everybody can access it.
While my serviceworker want to caching the data, it get 401 back. So it seems to be a problem with the authentication.
Maybe someone had already the same problem?
This happens when your resourcesToCache includes something that returns a 404 response. Make sure you have everything typed correctly. Also make sure that the scope is correct. You can check your worker scope using:
if("serviceWorker" in navigator) {
navigator.serviceWorker
.register(`worker.js`)
.then(registration => {
console.log("SW scope:", registration.scope);
});
}
If your project is not in your server domain root, doing something like this might help:
//your main js
if("serviceWorker" in navigator) {
navigator.serviceWorker
.register(`${window.location.pathname}worker.js`)
.then(registration => {
//do your thing
});
}
//your worker js
let resourcesToCache = [
'./',
'./index.html',
'./jquery-3.2.1.min.js',
'./pouchdb.min-6.4.1.js',
'./styles/inline.css',
'./scripts/app.js',
];
//...
As a side-note, you should be loading your libraries (jQuery, pouchdb), from a CDN to improve performance. Those can be cached too:
let resourcesToCache = [
'./',
'./index.html',
'https://code.jquery.com/jquery-3.3.1.min.js',
'https://cdnjs.cloudflare.com/ajax/libs/pouchdb/6.4.3/pouchdb.min.js',
'./styles/inline.css',
'./scripts/app.js',
];
This happened to me when I was developing locally on a windows machine and deploying on a linux server, the problem is with the path. You need to add a '.' before your path for it to be like "./" as follows:
var resourcesToCache = [
'./',
'./index.html',
'./jquery-3.2.1.min.js',
'./pouchdb.min-6.4.1.js',
'./styles/inline.css',
'./scripts/app.js'
];
This had happened to me when i was referring a file (that don't exist in the path specified) for caching. When i updated the path to the file, things got fine.
I am running a simple node script which starts chromedriver pointed at my website, scrolls to the bottom of the page, and writes the trace to trace.json.
This file is around 30MB.
I can't seem to load this file in chrome://tracing/, which is what I assume I would do in order to view the profile data.
What are my options for making sense of my trace.json file?
Here is my node script, in case that helps clarify what I am up to:
'use strict';
var fs = require('fs');
var wd = require('wd');
var b = wd.promiseRemote('http://localhost:9515');
b.init({
browserName: 'chrome',
chromeOptions: {
perfLoggingPrefs: {
'traceCategories': 'toplevel,disabled-by-default-devtools.timeline.frame,blink.console,disabled-by-default-devtools.timeline,benchmark'
},
args: ['--enable-gpu-benchmarking', '--enable-thread-composting']
},
loggingPrefs: {
performance: 'ALL'
}
}).then(function () {
return b.get('http://www.example.com');
}).then(function () {
// We only want to measure interaction, so getting a log once here
// flushes any previous tracing logs we have.
return b.log('performance');
}).then(function () {
// Smooth scroll to bottom.
return b.execute(`
var height = Math.max(document.documentElement.scrollHeight, document.body.scrollHeight, document.documentElement.clientHeight);
chrome.gpuBenchmarking.smoothScrollBy(height, function (){});
`);
}).then(function () {
// Wait for the above action to complete.
return b.sleep(5000);
}).then(function () {
// Get all the trace logs since last time log('performance') was called.
return b.log('performance');
}).then(function (data) {
// Write the file to disk.
return fs.writeFileSync('trace.json', JSON.stringify(data.map(function (s) {
return JSON.parse(s.message); // This is needed since Selenium outputs logs as strings.
})));
}).fin(function () {
return b.quit();
}).done();
Your script doesn't generate the correct format. The required data for each entry are located in message.message.params.
To generate a trace that can be loaded in chrome://tracing :
var fs = require('fs');
var webdriver = require('selenium-webdriver');
var driver = new webdriver.Builder()
.withCapabilities({
browserName : 'chrome',
loggingPrefs : { performance: 'ALL' },
chromeOptions : {
args: ['--enable-gpu-benchmarking', '--enable-thread-composting'],
perfLoggingPrefs: {
'traceCategories': 'toplevel,disabled-by-default-devtools.timeline.frame,blink.console,disabled-by-default-devtools.timeline,benchmark'
}
}
}).build();
driver.get('https://www.google.com/ncr');
driver.sleep(1000);
// generate a trace file loadable in chrome://tracing
driver.manage().logs().get('performance').then(function (data) {
fs.writeFileSync('trace.json', JSON.stringify(data.map(function (d) {
return JSON.parse(d['message'])['message']['params'];
})));
});
driver.quit();
The same script with python:
import json, time
from selenium import webdriver
driver = webdriver.Chrome(desired_capabilities = {
'loggingPrefs': { 'performance': 'ALL' },
'chromeOptions': {
"args" : ['--enable-gpu-benchmarking', '--enable-thread-composting'],
"perfLoggingPrefs" : {
"traceCategories": "toplevel,disabled-by-default-devtools.timeline.frame,blink.console,disabled-by-default-devtools.timeline,benchmark"
}
}
})
driver.get('https://stackoverflow.com')
time.sleep(1)
# generate a trace file loadable in chrome://tracing
with open(r"trace.json", 'w') as f:
f.write(json.dumps([json.loads(d['message'])['message']['params'] for d in driver.get_log('performance')]))
driver.quit()
Not sure if you know, the recommendation lib for parsing those thing is https://github.com/ChromeDevTools/devtools-frontend
Also, recommended categories are __metadata,benchmark,devtools.timeline,rail,toplevel,disabled-by-default-v8.cpu_profiler,disabled-by-default-devtools.timeline,disabled-by-default-devtools.timeline.frame,blink.user_timing,v8.execute,disabled-by-default-devtools.screenshot
It's very old question, but hope this helps new other guys.
I'm trying to test a (simple) directive that validates a text field to see if the inputted value is less than another controller's variable max value.
Here's my error:
IE 11.0.0 (Windows 7) Maximum value validator should be valid initially FAILED
Error: Unexpected request: GET app/layout/shell.html
No more request expected
at $httpBackend (C:/Projects/myProj/myProj/scripts/angular-mocks.js:1218:5)
at sendReq (C:/Projects/myProj/myProj/scripts/angular.js:9462:9)
at serverRequest (C:/Projects/myProj/myProj/scripts/angular.js:9179:9)
at processQueue (C:/Projects/myProj/myProj/scripts/angular.js:12914:11)
at Anonymous function (C:/Projects/myProj/myProj/scripts/angular.js:12930:27)
at Scope.prototype.$eval (C:/Projects/myProj/myProj/scripts/angular.js:14123:9)
at Scope.prototype.$digest (C:/Projects/myProj/myProj/scripts/angular.js:13939:15)
at Anonymous function (C:/Projects/myProj/myProj.test/directiveTests.js:11:3)
at invoke (C:/Projects/myProj/myProj/scripts/angular.js:4152:7)
at workFn (C:/Projects/myProj/myProj/scripts/angular-mocks.js:2255:11)
So looking around this seems to be associated with not setting up an AJAX call. Except, as you can see below, my directive doesn't have any associated service calls at all on it. Plus, why the heck is it trying a GET request for the shell html file? Where did that come from?
I've only written a few tests so far as I'm just starting this project, but my other tests worked just fine. I'm running Karma if that might make a difference. I'm stumped though because my tests look like the example tests that are out there. If I debug through, everything seems great through the end of the test but I get the error after the test completes and the test fails with this error.
OK code time.
My directive:
(function() {
'use strict';
var app = angular.module('app');
app.directive('maxValue', function() {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, ele, attrs, ctrl) {
ctrl.$parsers.unshift(function(value) {
var valid;
if (value) {
var maxValue = scope.$eval(attrs.maxValue);
valid = parseInt(value, 10) <= maxValue;
}
return valid ? valid : undefined;
});
}
};
});
})();
and my tests:
describe("Maximum value validator", function() {
var $scope, form;
beforeEach(module('app'));
beforeEach(inject(function($compile, $rootScope) {
var element = angular.element('<form name="form"><input type="text" name="value" ng-model="value" max-value="maxValue" /></form>');
$scope = $rootScope;
$scope.value = 0;
$scope.maxValue = 100;
$compile(element)($scope);
$scope.$digest();
}));
it('should be valid initially', function () {
expect($scope.form.value.$valid).toBe(true);
});
it('should be valid when value is the same as the max value', function() {
$scope.form.value.$setViewValue('100');
expect($scope.form.value.$valid).toBe(true);
});
it('should be invalid when the value is greater than the max value', function() {
$scope.form.value.$setViewValue('101');
expect($scope.form.value.$valid).toBe(false);
});
});
#rball and I have came to the conclusion that the following fixed the "module not found" error:
var mod = angular.module('uiRouterNoop', []);
mod.service('$state', function () {
return {}
});
mod.service('$urlRouter', function () {
return {};
});
Then in the spec
beforeEach(module('uiRouterNoop'));
It is an important practice in angular to separate modules where need be. Most SPA's tie every module to the same one such as 'app'. But it is good to separate them for testing purposes such as these and can prevent dependency problems when testing due to complex mock scenarios.