Calculating total in cypress - cypress

I am trying to calculate the total price in the following way. However, when I log the total value at the bottom, I always get 0 logged.
I wish to store total in a variable so I can use it later on to compare values.
let total = 0;
cy.get('[cy-data="order-summary-products-product"]').each(
($product, index, $list) => {
const productQuantity = $product.attr("cy-data-product-quantity");
const productPrice = $product.attr("cy-data-product-price");
total += productPrice * productQuantity;
cy.wrap($product)
.find('[cy-data="order-summary-products-modifier"]')
.each(($modifier, index2, $list2) => {
const modifierQuantity = $modifier.attr("cy-data-modifier-quantity");
const modifierPrice = $modifier.attr("cy-data-modifier-price");
total += modifierPrice * modifierQuantity;
});
}
);
cy.log(total) //Always get 0 logged

Cypress has a env() method that you can use globally to store whatever you need.
Cypress.env('totalQuantity') = 0;
cy.get('[cy-data="order-summary-products-product"]').each(
($product, index, $list) => {
const productQuantity = $product.attr("cy-data-product-quantity");
const productPrice = $product.attr("cy-data-product-price");
Cypress.env('totalQuantity') += productPrice * productQuantity;
cy.wrap($product)
.find('[cy-data="order-summary-products-modifier"]')
.each(($modifier, index2, $list2) => {
const modifierQuantity = $modifier.attr("cy-data-modifier-quantity");
const modifierPrice = $modifier.attr("cy-data-modifier-price");
Cypress.env('totalQuantity') += modifierPrice * modifierQuantity;
});
});

Related

RxJS: How to create an event manager with a buffer that flush based on multiple conditions

I have a requirement to create an event manager with a buffer that flushes if one of 3 criteria is met:
2 seconds pass
50 events received
Flush on demand if requested by user
All criteria will reset when buffer flushes (reset the 2 second timer, reset the 50 events count...etc)
This is what I've implemeted so far and it seems to be working but I'm wondering if there's a better way to achieve this requirement.
import { interval, merge, Subject, Subscription } from "rxjs";
import { bufferWhen, filter, tap } from "rxjs/operators";
class Foo {
private eventListener: Subject < string > = new Subject();
private eventForceFlushListener: Subject < void > = new Subject();
private eventBufferSizeListener: Subject < void > = new Subject();
private maxBufferSize = 50;
private currentBufferSize = 0;
/**
*
* Buffer that will flush if one of the 3 criteria is met:
* - 50 texts are received
* - 2 seconds pass
* - Force flush by user
*/
private eventBufferOperator = () => merge(interval(2 * 1000), this.eventForceFlushListener, this.eventBufferSizeListener);
/**
* Flush buffer if requested by user. (for example flush buffer before app close so we dont lose buffered texts)
*/
public forceFlush() {
this.eventForceFlushListener.next();
}
/**
* Method used by users to emit texts to the listener
*/
public emitText(text: string) {
this.eventListener.next(text);
this.currentBufferSize = this.currentBufferSize + 1;
if (this.currentBufferSize == this.maxBufferSize) {
// flush all evenst when maxBufferSize is reached
this.eventBufferSizeListener.next();
// buffer size is reset below in the function that's inside "subscribe"
}
}
public subscribeToEventListerenr() {
const eventListenerSubscription = this.eventListener
.pipe(
tap((text) => text.trim()),
filter((text) => true),
bufferWhen(this.eventBufferOperator),
filter((events) => !!events.length)
)
.subscribe((x) => {
console.log(x);
this.maxBufferSize = 0; // reset size buffer
});
return eventListenerSubscription;
}
}
Users then can use this event manager as follows:
const eventManager = new Foo();
eventManager.subscribeToEventListerenr();
eventManager.emitText('message1');
eventManager.emitText('message2');
5 seconds pass
5 events received
Flush on demand if requested by user
const { race, Subject, take, share, buffer, tap, bufferCount, bufferTime, startWith, exhaustMap, map } = rxjs;
const observer = (str) => ({
subscribe: () => console.log(`${str} -> subscribe`),
next: () => console.log(`${str} -> next`),
unsubscribe: () => console.log(`${str} -> unsubscribe`),
});
const event$ = new Subject()
const share$ = event$.pipe(map((_, i) => i + 1), share());
const flush$ = new Subject();
const trigger$ = flush$.pipe(tap(observer('flush$')));
const bufferSize$ = share$.pipe(startWith(null), bufferCount(5), tap(observer('BufferSize 5')));
const bufferTime$ = share$.pipe(bufferTime(5000), tap(observer('5 Sec')));
const race$ = race(bufferTime$, trigger$, bufferSize$).pipe(take(1));
const buffer$ = share$.pipe(exhaustMap(() => race$));
share$.pipe(buffer(buffer$)).subscribe((x) => console.log(x));
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/7.5.6/rxjs.umd.min.js"></script>
<button onclick="event$.next()">event</button>
<button onclick="flush$.next()">flush</button>
https://stackblitz.com/edit/rxjs-5qgaeq
My final answer
window
bufferTime
const bufferBy$ = new Subject<void>();
const maxBufferSize = 3;
const bufferTimeSpan = 5000;
source$.pipe(
window(bufferBy$),
mergeMap(bufferTime(bufferTimeSpan, null, maxBufferSize)),
).subscribe(...);
https://stackblitz.com/edit/rxjs-hoafkr

Filter & Delete rows of data based off of column value fast! (Google Sheets)

Is there a way to filter the data in column Q off my google sheet faster then reading line one by one. There is daily about 400+ lines it needs to scan through and I need to delete every row of data if the data in column Q is less than 1 right now watching it, it takes about 10+ minutes.
function UpdateLog() {
var returnSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('CancelRawData');
var rowCount = returnSheet.getLastRow();
for (i = rowCount; i > 0; i--) {
var rrCell = 'Q' + i;
var cell = returnSheet.getRange(rrCell).getValue();
if (cell < 1 ){
returnSheet.deleteRow(i);
}
}
{
SpreadsheetApp.getUi().alert("🎉 Congratulations, your data has been updated", SpreadsheetApp.getUi().ButtonSet.OK);
}
}
Try it this way:
function UpdateLog() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('Sheet0');
const vs = sh.getDataRange().getValues();
let d = 0;
vs.forEach((r, i) => {
if (!isNaN(r[16]) && r[16] < 1){
sh.deleteRow(i + 1 - d++);
}
});
}
This is a bit quicker
function UpdateLog() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('Sheet0');
const vs = sh.getDataRange().getValues().filter(r => !isNaN(r[16]) && r[16] < 1);
sh.clearContents();
sh.getRange(1,1,vs.length,vs[0].length).setValues(vs);
}

onEdit checkbox then IMPORTRANGE

I'm trying to combine a onEdit script with an import range script, I tried using "if" to check if there's a single TRUE checkbox on the selected range but the import range part does not work only the checkbox part.
I need to import only after a single TRUE checkbox is enabled on column 7 otherwise the other spreadsheet glitches.
Source for the checkbox validation script: https://stackoverflow.com/a/71798583/18249133
function onEdit(e) {
const ss = SpreadsheetApp.getActiveSheet()
const { range: { columnStart, rowStart, rowEnd }, value } = e
if (value === "FALSE") return;
const checkRowStart = 4
const checkRowEnd = 200
const checkColumn = 7
if (columnStart === checkColumn && checkRowStart <= rowStart && checkRowEnd >= rowEnd) {
for (let i = 0; i < checkRowEnd; i++) {
ss.getRange(i + checkRowStart, checkColumn).setValue(false)
}
ss.getRange(rowStart, columnStart).setValue(true)
}
}
Import range script
function import(){
importRange(
"SPREADSHEET_ID",
"SHEET NAME + RANGE",
"SPREADSHEET_ID",
"SHEET NAME + RANGE",
);
};
function importRange(sourceID, sourceRange, destinationID, destinationRangeStart) {
const sourceSS = SpreadsheetApp.openById(sourceID);
const sourceRng = sourceSS.getRange(sourceRange);
const sourceVals = sourceRng.getValues();
const destinationSS = SpreadsheetApp.openById(destinationID);
const destStartRange = destinationSS.getRange(destinationRangeStart);
const destSheet = destinationSS.getSheetByName(destStartRange.getSheet().getName());
const destRange = destSheet.getRange(
destStartRange.getRow(),
destStartRange.getColumn(),
sourceVals.length,
sourceVals[0].length
);
destRange.setValues(sourceVals);
};
Thanks in advance :]

Can you use if statements in .nest(). If not what is the best way to assign labels to array elements so they fit in several groups

Is it possible to use if statements within .nest()? I'm trying to populate a column with several keys, but instead of looking for a name I want to assign a name/value to individual rows based on whether the value in the column is within a certain range of numbers. I have looked at the D3 Nest Tutorial and examples and I'm still having a hard time. This is the code I have at the moment, which isn't working. Any help would be greatly appreciated!
fireballData.forEach( d => {
years.forEach(year => {
const latitude = d['Latitude (deg.)'];
const impactEnergy = d['Calculated Total Impact Energy (kt)'];
const impactTest = +impactEnergy;
const impactLevel = nest('impactTest')
.key(function(d) { if (d.impactTest < .5) {return "impactA" }});
// .sortKeys(d3.ascending)
// .key(function(d) { return d.impactEnergy; })
// .sortKeys(function(a,b) {
// return impactEnergy.indexOf(a) - impactEnergy.indexOf(b); })
// .sortValues(function(a,b) { return ((a.who < b.who)
// ? -1
// : 1);;
const longitude = d['Longitude (deg.)'];
const impactYear = d['PeakBrightnessDate_TimeUT'];
const row = {
//year,
impactLevel,
impactEnergy,
latitude,
longitude,
impactYear
};
console.log(row);
});
});
Just to be a bit more clear, I want to assign five or six impact levels to the column impactLevel based on how big of a value impactEnergy is. This would then leave each row with the impactLevel id (ie impactLevel1) followed by the rest of data of that object. Any solustions or suggestions are great appreciated! I am still very new to d3 and I am still learning the in's and out's.
So for what I was trying to accomplish using .nest wasn't a good solution. The better way of going about creating the new array was to use .map.
export const loadAndProcessData = () =>
Promise
.all([
csv('data.csv')
])
.then(([fireballData]) => {
const minYear = 2015;
const maxYear = 2100;
const years = range(minYear, maxYear + 1);
const data = [];
// Special thanks to Darshit Shah for helping me figure this bit out
const showData = fireballData.map(d =>{
const impactYear = d['PeakBrightnessDate_TimeUT'];
const latitude = d['Latitude (deg.)'];
const longitude = d['Longitude (deg.)'];
const impactEnergy = +d['Calculated Total Impact Energy (kt)'];
const target = impactEnergy;
const type = 'Impact Year: ' + impactYear + ', Latitude: ' + latitude + ', Longitude: ' + longitude;
return {
sorce: (impactEnergy < 0.15 ? "0-0.15" : (impactEnergy < 0.25 ? "0.15-0.25" : (impactEnergy < 0.5 ? "0.25-0.5" : ">0.5"))),
target,
type
}
});
data.push(showData);
return data;
`

Creating object which can be passed to view

I want to make a loan repayment payment plan. I need to put 4 values in a row for each month (loan balance before month, monthly interest repaid, balance repaid and loan at the end of month). I can calculate all these data in controller but I am unable to pass them to view.
Calculation of all elements is ok but I am unable to pass the object to view.
public function show()
{
$fLoanAmount = 10000;
$fAPR = 8.3;
$iTerm = 12;
$monthlyInterest = $fAPR/1200;
$payment = round($this->calculateMonthlyPayments($fLoanAmount, $fAPR, $iTerm),2);
for ($n = 0; $n < $iTerm; $n++) {
$loanBalance = $fLoanAmount;
$monthlyInterest = $loanBalance * $fAPR/1200;
$monthlyBalanceRepayment = $payment - $monthlyInterest;
$fLoanAmount = $loanBalance - $monthlyBalanceRepayment;
$paymentPlan = collect([
'loanBalance' => $loanBalance,
'monthlyInterest' => $monthlyInterest,
'monthlyBalanceRepayment' => $monthlyBalanceRepayment,
'loanAmmount' => $fLoanAmount,
]);
}
return view('plan', compact('paymentPlan'));
}

Resources