How to come out of method execution based on a condition in protractor? - protractor

I'm a Java developer and new to protractor. I'm trying to iterate through a dynamic web table in a web page and trying to find out a particular user name and open his profile. Once I open his profile, I want my test method to stop execution and return. But the return statement doesn't work and the for loop still runs. Could anyone please help me with this? Below is my method.
searchUser() {
// Iterate through the user listing table
browser.driver.findElement(by.css('.slds-max-medium-table--stacked-horizontal')).then(function (table) {
table.findElement(by.tagName('tbody')).then(function (tbody) {
tbody.findElements(by.tagName('tr')).then(function (rows) {
for (var i = 0; i < rows.length; i++) {
rows[i].findElements(by.tagName('td')).then(function (cols) {
cols[1].getText().then(function (user) {
if (user == "ADAM SMITH") {
// found user, open his profile
cols[1].click();
return;
}
});
});
}
// user not found in the current page. Click on next page and continue search
element(by.xpath("//*[#id='main']/div/app-users-profile/users-listing/form/div[2]/div/div/div/div[2]/div/button")).click();
browser.sleep(3000);
var currentPage = new LoginPage();
currentPage.searchUser();
});
});
});
}

I try to make as less differences as I can.
async function searchUser () {
let result = false;
while (!result) {
const table = browser.$('.slds-max-medium-table--stacked-horizontal');
const tbody = table.$('tbody');
const rows = tbody.$$('tr');
await rows.map(async (row) => {
const column = row.findElements(by.tagName('td')).get(1);
const name = await column.getText();
if (name === 'ADAM SMITH') {
await column.click();
result = true;
}
});
if (!result) {
await element(by.xpath("//*[#id='main']/div/app-users-profile/users-listing/form/div[2]/div/div/div/div[2]/div/button")).click();
await browser.sleep(3000);
const currentPage = new LoginPage();
await currentPage.searchUser();
}
}
}

Related

Mongoose - MongoDB | "Query was already executed" error on query in loop

I'm trying to collection queries in the while loop. But I'm getting a "Query was already executed" error. How can I do that? I have a custom field and I need to make sure it is unique. I also need to use this function elsewhere.
async function createRandomID() {
let id = Math.random().toString(36).slice(2, 6).toUpperCase();
let unique = false;
while (!unique) {
await Deed.findOne({ deedId: id }, async (err, doc) => {
if (!doc) {
unique = true;
}
else {
id = Math.random().toString(36).slice(2, 6).toUpperCase();
}
})
}
return id;
}
const addNewDeed = asyncErrorWrapper(async (req, res, next) => {
let information = req.body;
const deedId = await createRandomID();
/*Other Operations...*/
});

Flutter PWA service worker fails to successfully register

I've built my flutter app and have the pwa version of it, hosted it on windows server IIS 10 with a valid ssl certificate on subdomain like Https://pwa.mydomain.com, but when I visit the page, it doesn't show the Install app button on chrome. How can I solve this?
What I've done so far:
Removed the references to files that did not exist anymore in the project.
Here is my service worker:
'use strict';
const MANIFEST = 'flutter-app-manifest';
const TEMP = 'flutter-temp-cache';
const CACHE_NAME = 'flutter-app-cache';
const RESOURCES = {
".dart_tool/package_config.json": "23791ac6df06edd3cb7ca99ab6949a5a",
".dart_tool/package_config_subset": "8453ab6a2adbaeda61d2d58965841223",
".dart_tool/version": "a13ed25c1389038783693bec771e71f6",
"assets/assets/images/svgIcon/wifiOff.svg": "ca97536b42e250214b667a606455a58f",
"assets/FontManifest.json": "fba83cca6cbe4083e6cc0498e15a1a6f",
"assets/fonts/MaterialIcons-Regular.otf": "4e6447691c9509f7acdbf8a931a85ca1",
"assets/NOTICES": "0e94f133a57e1e05b650363a497d95b0",
"assets/packages/cupertino_icons/assets/CupertinoIcons.ttf": "6d342eb68f170c97609e9da345464e5e",
"favicon.png": "19e188c1100dbd706d3d81309d478996",
"icons/launcher_logo192.png": "ea22e4258d33a9a184a426b38f3e6f46",
"icons/launcher_logo512.png": "19e188c1100dbd706d3d81309d478996",
"index.html": "fde3d71f9f8a4623bd98e956040169d2",
"/": "fde3d71f9f8a4623bd98e956040169d2",
"lib/main.dart": "5515740aeb62c25aa7692184d00b90b1",
"lib/src/qr_code_scanner_web.dart": "50b70d762e80fedd228974e786e8f38a",
"lib/src/qr_code_scanner_web_impl.dart": "a0f12d21cc75aefe84f6fbf9c1e0307e",
"lib/src/qr_code_scanner_web_impl_no_web.dart": "11e3ab6339d41ded6e650c96120e7560",
"main.dart.js": "6161190dc35f953037fb5c0e7db4f0e6",
"manifest.json": "a281fd45bea620b437523746b29b93d2",
"pubspec.lock": "6c06cc012f6524824b77f7286b6e256e",
"pubspec.yaml": "b36c6ef43dcaa5a79fc412a8368306cf",
"version.json": "cbca785ad23c1984a075073af0a61003"
//Removed for brevity
};
// The application shell files that are downloaded before a service worker can
// start.
const CORE = [
"/",
"main.dart.js",
"index.html",
"assets/NOTICES",
"assets/AssetManifest.json",
"assets/FontManifest.json"];
// During install, the TEMP cache is populated with the application shell files.
self.addEventListener("install", (event) => {
self.skipWaiting();
return event.waitUntil(
caches.open(TEMP).then((cache) => {
return cache.addAll(
CORE.map((value) => new Request(value, {'cache': 'reload'})));
})
);
});
// During activate, the cache is populated with the temp files downloaded in
// install. If this service worker is upgrading from one with a saved
// MANIFEST, then use this to retain unchanged resource files.
self.addEventListener("activate", function(event) {
return event.waitUntil(async function() {
try {
var contentCache = await caches.open(CACHE_NAME);
var tempCache = await caches.open(TEMP);
var manifestCache = await caches.open(MANIFEST);
var manifest = await manifestCache.match('manifest');
// When there is no prior manifest, clear the entire cache.
if (!manifest) {
await caches.delete(CACHE_NAME);
contentCache = await caches.open(CACHE_NAME);
for (var request of await tempCache.keys()) {
var response = await tempCache.match(request);
await contentCache.put(request, response);
}
await caches.delete(TEMP);
// Save the manifest to make future upgrades efficient.
await manifestCache.put('manifest', new Response(JSON.stringify(RESOURCES)));
return;
}
var oldManifest = await manifest.json();
var origin = self.location.origin;
for (var request of await contentCache.keys()) {
var key = request.url.substring(origin.length + 1);
if (key == "") {
key = "/";
}
// If a resource from the old manifest is not in the new cache, or if
// the MD5 sum has changed, delete it. Otherwise the resource is left
// in the cache and can be reused by the new service worker.
if (!RESOURCES[key] || RESOURCES[key] != oldManifest[key]) {
await contentCache.delete(request);
}
}
// Populate the cache with the app shell TEMP files, potentially overwriting
// cache files preserved above.
for (var request of await tempCache.keys()) {
var response = await tempCache.match(request);
await contentCache.put(request, response);
}
await caches.delete(TEMP);
// Save the manifest to make future upgrades efficient.
await manifestCache.put('manifest', new Response(JSON.stringify(RESOURCES)));
return;
} catch (err) {
// On an unhandled exception the state of the cache cannot be guaranteed.
console.error('Failed to upgrade service worker: ' + err);
await caches.delete(CACHE_NAME);
await caches.delete(TEMP);
await caches.delete(MANIFEST);
}
}());
});
// The fetch handler redirects requests for RESOURCE files to the service
// worker cache.
self.addEventListener("fetch", (event) => {
if (event.request.method !== 'GET') {
return;
}
var origin = self.location.origin;
var key = event.request.url.substring(origin.length + 1);
// Redirect URLs to the index.html
if (key.indexOf('?v=') != -1) {
key = key.split('?v=')[0];
}
if (event.request.url == origin || event.request.url.startsWith(origin + '/#') || key == '') {
key = '/';
}
// If the URL is not the RESOURCE list then return to signal that the
// browser should take over.
if (!RESOURCES[key]) {
return;
}
// If the URL is the index.html, perform an online-first request.
if (key == '/') {
return onlineFirst(event);
}
event.respondWith(caches.open(CACHE_NAME)
.then((cache) => {
return cache.match(event.request).then((response) => {
// Either respond with the cached resource, or perform a fetch and
// lazily populate the cache.
return response || fetch(event.request).then((response) => {
cache.put(event.request, response.clone());
return response;
});
})
})
);
});
self.addEventListener('message', (event) => {
// SkipWaiting can be used to immediately activate a waiting service worker.
// This will also require a page refresh triggered by the main worker.
if (event.data === 'skipWaiting') {
self.skipWaiting();
return;
}
if (event.data === 'downloadOffline') {
downloadOffline();
return;
}
});
// Download offline will check the RESOURCES for all files not in the cache
// and populate them.
async function downloadOffline() {
var resources = [];
var contentCache = await caches.open(CACHE_NAME);
var currentContent = {};
for (var request of await contentCache.keys()) {
var key = request.url.substring(origin.length + 1);
if (key == "") {
key = "/";
}
currentContent[key] = true;
}
for (var resourceKey of Object.keys(RESOURCES)) {
if (!currentContent[resourceKey]) {
resources.push(resourceKey);
}
}
return contentCache.addAll(resources);
}
// Attempt to download the resource online before falling back to
// the offline cache.
function onlineFirst(event) {
return event.respondWith(
fetch(event.request).then((response) => {
return caches.open(CACHE_NAME).then((cache) => {
cache.put(event.request, response.clone());
return response;
});
}).catch((error) => {
return caches.open(CACHE_NAME).then((cache) => {
return cache.match(event.request).then((response) => {
if (response != null) {
return response;
}
throw error;
});
});
})
);
}
This is the error I'm getting:
Uncaught (in promise) TypeError: Failed to execute 'addAll' on 'Cache': Request failed
I'm curious whether this error has something to do with CORS or not.
Thanks.

PWA problem with Vue3+service worker+keep-alive

I have a problem with Vue3+service worker+keep-alive.
I use keep-live in template
<q-page-container>
<router-view v-slot="{ Component }">
<keep-alive :include="['WorkPage']">
<component :is="Component" :key="$route.fullPath"/>
</keep-alive>
</router-view>
</q-page-container>
create queue
createWorkQueue = new Queue('createWorkQueue', {
onSync: async ( {queue} ) => {
let entry
while (entry = await queue.shiftRequest()) {
try {
await fetch(entry.request);
const channel = new BroadcastChannel('sw-messages-work');
channel.postMessage({msg: 'offline-work-uploaded'});
} catch (error) {
await queue.unshiftRequest(entry);
throw error;
}
}
}
})
addEventListener('fetch'
self.addEventListener('fetch', (event) => {
if (event.request.url.endsWith('/api/ins_new_work')) {
const bgSyncLogic = async () => {
try {
const response = await fetch(event.request.clone())
return response
} catch (error) {
await createWorkQueue.pushRequest({request: event.request})
return error
}
}
event.respondWith(bgSyncLogic())
}
})
when in offline I send form - createWorkQueue.pushRequest hangs to 5 minutes
if I delete from keep-alive - WorkPage - then pushRequest works well
but I need keep-alive page. How can I solve this?
I found!!
I use IndexedDB library and for show offline message I read from DB information
const db = await openDB('workbox-background-sync')
but in first time - table 'requests' don't create
I insert next code
const db = await openDB('workbox-background-sync', undefined, { upgrade(db) { db.createObjectStore('requests') }})
and works well

Mongoose/Mongodb, update each doc query, very slow

I have this update query in mongoose. It's 1600 posts and takes like 5 min to run.
What's the bottleneck? Am I using the wrong approach?
export const getAndStoreLatestKPI = async () => {
console.log("start kpi");
try {
const marketCaps = await getKPI();
const stocks = await mongoose.model("stock").find().exec();
for (const stock of stocks) {
const marketCap = marketCaps.find(
(marketCap) => marketCap.i === stock.insId
);
if (marketCap != null) {
const marketCapAdjustedVal =
stock.country === "Finland" ? marketCap.n * 10 : marketCap.n;
const update = {
marketCap: marketCapAdjustedVal,
};
console.log(marketCapAdjustedVal);
await mongoose
.model("stock")
.findOneAndUpdate({ insId: stock.insId }, { update });
}
}
console.log("done");
return Promise.resolve();
} catch (err) {
return Promise.reject(err);
}
};
export const getKPI = async (kpiId: number) => {
try {
const kpiFetch = await Axios.get(someurl);
return Promise.resolve(kpiFetch.data.values);
} catch (err) {
return Promise.reject(err);
}
};
So the main bottle neck is your for loop. for each stock item you perform several "expensive" actions such as data fetching from external API + a single update, and you're doing them 1 by 1.
What I would recommend you doing is looping on several items at once. similar to the idea multithreading.
There are several different solutions on how to do it in nodejs for example nodejs worker threads
However I personally use and recommend using bluebird which gives you this ability and many others straight out of the box.
Some sample code:
import Bluebird = require('bluebird');
const stocks = await mongoose.model("stock").find().exec();
await Bluebird.map(stocks, async (stock) => {
const marketCap = marketCaps.find(
(marketCap) => marketCap.i === stock.insId
);
if (marketCap != null) {
const marketCapAdjustedVal =
stock.country === "Finland" ? marketCap.n * 10 : marketCap.n;
const update = {
marketCap: marketCapAdjustedVal,
};
console.log(marketCapAdjustedVal);
await mongoose
.model("stock")
.findOneAndUpdate({ insId: stock.insId }, { update });
}
}, {concurrency: 25})
// concurrency details how many concurrent process run parallel. the heavier they are the less you want concurrent for obvious reasons.

Combining koa-passport with koa-router (getting user data)

I have created a login which is able to login a user and store the user if they are new in the database.
The user is then redirected to / and then is checked if they are authenticated or not, see below (app.js):
.get('/', function* () {
if (this.isAuthenticated()) {
yield this.render('homeSecure', {}); // <-- need user data here
} else {
yield this.render('homePublic', {});
}
As I commented in the code, I would like to send the user object of which is logged in. I have no idea how to get a hold of the id of the person logged in as the documentation for koa in general is not as complete as that of express.
I am using koa-generic-session-mongo to handle my sessions. Here is my GoogleStrategy (auth.js):
var user = null;
// ...
var GoogleStrategy = require('passport-google').Strategy;
passport.use(new GoogleStrategy({
returnURL: 'http://localhost:' + (process.env.PORT || 3000) + '/auth/google/callback',
realm: 'http://localhost:' + (process.env.PORT || 3000)
},
function (identifier, profile, done) {
var emails = new Array();
for (var i = 0; i < profile.emails.length; i++) {
emails.push(profile.emails[i].value);
}
co(function* () {
yield users.findOne({
emails: emails
});
});
if (user === null) { // first time signin, create account
co(function* () {
user = {
id: 1,
name: profile.displayName,
emails: emails
};
yield users.insert(user);
});
}
console.log(user);
done(null, user);
}));
publicRouter
.get('/', function* () {
if (this.isAuthenticated()) {
yield this.render('homeSecure', {
user: this.req.user
});
} else {
yield this.render('homePublic', {});
}
})...
Disclaimer: I've not used koa-passport, I've just looked at the code.
According to the source code of the koa-passport library, the property you're looking for is passport.user, and is used like so:
app.use( function*(){
var user = this.passport.user
})
Thus, your code sample would become
.get('/', function* () {
if (this.isAuthenticated()) {
yield this.render('homeSecure', this.passport.user );
} else {
yield this.render('homePublic', {});
}
If that does not work, this file leads me to suspect that koa-passport follows the standard passport interface and provides this.user to the request.