Javascript Class set private var on public function - javascript

can i set variables on the scope of the class to be used later?
example
class TestClass {
#key = '';
#reference = '';
#onReturn = () => {};
constructor({ key } = {}) {
this.#key = key || this.#key;
this.#onReturn = onReturn || this.#onReturn;
}
login(username, password) {
this.#submit(username, password);
};
#submit(username, password) {
fetch(
`/login/${this.#key}`,
)
.then(response => response.json())
.then((json) => {
this.#handleResponse(json);
})
};
#handleResponse(json) {
this.#reference = json.reference;
this.#onReturn();
};
token() {
console.log(this.#key, this.#reference); // "blabla", empty
};
};
const Test = new TestClass({ // initializing the class
key: 'blabla',
onReturn: tokenSubmit
});
const onLoginSubmit = () => {
Test.login(username, password); // running a fetch which will set a private var
};
const tokenSubmit = () => {
Test.token(); // private var returns empty
};
which has two public methods login and token
where the token should log the key and the reference
as a result i do get the key which was set on the constructor
but the reference which was set while handling a fetch returns empty

Following up on #vlaz's comment, try the following test code:
async function test() {
const Test = new TestClass({ key: 'blabla' }); // initializing the
class
await LoginModule.login({ username, password }); // running a fetch which will set a private var
LoginModule.token(); // private var returns empty
}
The addition of await waits for the fetch to complete before proceeding to the next line, calling LoginModule.token().
For this to work, you'll also need to modify #submit to return fetch's promise:
#submit({ username, password }) {
return fetch(
`/login/${this.#key}`,
)
.then(response => response.json())
.then((json) => {
this.#handleResponse({ json });
})
};

Related

Unable to mock a class method in Javascript/Typescript

I am not getting any clue how to mock a method. I have to write a unit test for this function:
index.ts
export async function getTenantExemptionNotes(platform: string) {
return Promise.all([(await getCosmosDbInstance()).getNotes(platform)])
.then(([notes]) => {
return notes;
})
.catch((error) => {
return Promise.reject(error);
});
}
api/CosmosDBAccess.ts
import { Container, CosmosClient, SqlQuerySpec } from "#azure/cosmos";
import { cosmosdbConfig } from "config/Config";
import { Workload } from "config/PlatformConfig";
import { fetchSecret } from "./FetchSecrets";
export class CosmoDbAccess {
private static instance: CosmoDbAccess;
private container: Container;
private constructor(client: CosmosClient) {
this.container = client
.database(cosmosdbConfig.database)
.container(cosmosdbConfig.container);
}
static async getInstance() {
if (!CosmoDbAccess.instance) {
try {
const connectionString = await fetchSecret(
"CosmosDbConnectionString"
);
const client: CosmosClient = new CosmosClient(connectionString);
// Deleting to avoid error: Refused to set unsafe header "user-agent"
delete client["clientContext"].globalEndpointManager.options
.defaultHeaders["User-Agent"];
CosmoDbAccess.instance = new CosmoDbAccess(client);
return CosmoDbAccess.instance;
} catch (error) {
// todo - send to app insights
}
}
return CosmoDbAccess.instance;
}
public async getAllNotesForLastSixMonths() {
const querySpec: SqlQuerySpec = {
// Getting data from past 6 months
query: `SELECT * FROM c
WHERE (udf.convertToDate(c["Date"]) > DateTimeAdd("MM", -6, GetCurrentDateTime()))
AND c.IsArchived != true
ORDER BY c.Date DESC`,
parameters: [],
};
const query = this.container.items.query(querySpec);
const response = await query.fetchAll();
return response.resources;
}
}
export const getCosmosDbInstance = async () => {
const cosmosdb = await CosmoDbAccess.getInstance();
return cosmosdb;
};
index.test.ts
describe("getExemptionNotes()", () => {
beforeEach(() => {
jest.resetAllMocks();
});
it("makes a network call to getKustoResponse which posts to axios and returns what axios returns", async () => {
const mockNotes = [
{
},
];
const cosmosDBInstance = jest
.spyOn(CosmoDbAccess, "getInstance")
.mockReturnValue(Promise.resolve(CosmoDbAccess.instance));
const kustoResponseSpy = jest
.spyOn(CosmoDbAccess.prototype, "getAllNotesForLastSixMonths")
.mockReturnValue(Promise.resolve([mockNotes]));
const actual = await getExemptionNotes();
expect(kustoResponseSpy).toHaveBeenCalledTimes(1);
expect(actual).toEqual(mockNotes);
});
});
I am not able to get instance of CosmosDB or spyOn just the getAllNotesForLastSixMonths method. Please help me code it or give hints. The complexity is because the class is singleton or the methods are static and private

The fetch code in onNewScanResult is executed more than once once a QR code has been scanned, and also updating database. How to stop it from running?

executing the fetch code in onNewScanResult multiplt time and hence updating the database accordingly................
initialization of qr scanner.........
this.html5QrcodeScanner = new Html5QrcodeScanner(
qrcodeRegionId,
config,
verbose
); ```Executing scanner when qrcode is scanned```
this.html5QrcodeScanner.render(
this.props.qrCodeSuccessCallback,
this.props.qrCodeErrorCallback
);
}
}
this is main qr code class........
class QrCode extends React.Component {
constructor() {
super();
this.state = {
decodedResults: [],
};
this.onNewScanResult = this.onNewScanResult.bind(this);
}
this is where the executing multiple time is happing.......
onNewScanResult(decodedText, decodedResult) {
`geting data from loacal storage as we saved data earlier in the process about acess level`
const qrRes = decodedText;
const obj = JSON.parse(qrRes);
const token = localStorage.getItem("user");
const userData = JSON.parse(token);
const username = userData[0].userId;
const accesslevel = userData[0].accessLevel;
const result = JSON.parse(qrRes);
const ele = result.ele_name;
const newdata = { ele, username, accesslevel };
const data = {
Element_detail: obj,
accessLevel: newdata.accesslevel,
};
const verifyUser = localStorage.getItem("accessLeveldetails");
const accessdetail = JSON.parse(verifyUser);
```checking is user is verified or not```......
`checking the acess level you can ignore the checking focus on fetch part`....
This particular part is we have to stop executing multiple time so database is only entered with one value
if (accessdetail.accessLevel === data.accessLevel) {
try { ``` this fetch is updating database with multiple entries```
fetch(
data.accessLevel === 20
? `/v0/all_elements_image`
: `/v0/${accessdetail.msg}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(obj),
}
).then((res) => {
console.log(res);
if (!res) {
throw res;
}
return res.json();
});
} catch (error) {
console.log("Error:", error);
}
} else {
alert("WRONG USER");
}
}
}

How wait for data(Array) from server and then push something into it in js?

I have problem with my code, problem is i get array from server with async function (getData()) and then i want push one object into it but it doesn't work and have error like this :
sandbox.js:61 Uncaught TypeError: Cannot read properties of undefined (reading 'push')
at submitData (sandbox.js:61)
at handleInputs (sandbox.js:44)
at HTMLButtonElement.<anonymous> (sandbox.js:35)
and the code is here :
var dataBase;
const getData = async() => {
const url = 'http://localhost:8080/readData';
const res = await fetch(url);
const data = awair res.json();
dataBase = data;
}
const handleInputs = () => {
if (userName.value === "" && password.value === "" && repeatPassword.value === "" && checkTerms.checked) {
alert('Please fill the input');
} else {
if (password.value === repeatPassword.value) {
getData();
submitData();
renderUser();
form.reset();
} else {
alert('Password does not match with repeat password input')
}
}
}
const submitData = () => {
let userObj = {
userName: userName.value,
password: password.value,
id: countId++
}
dataBase.push(userObj); // problem here
sendData();
}
and how can i fix it ?
Here, I have removed the functions not declared here for now. You can add it later.
You are getting this error because you have not initialized database with any value, here an array
I am returning Promise to wait till the user is fetched.
Note: You were having the same variable dataBase for saving newly fetched data. I have created a new data variable for saving newly fetched data and database variable for saving it for further use.
let newData;
let dataBase =[];
const getData = () => {
return new Promise(async(resolve, reject) => {
const url = 'https://jsonplaceholder.typicode.com/users/1';
const res = await fetch(url);
const data = await res.json();
console.log(data);
newData = data;
resolve();
})
}
const handleInputs = async () => {
await getData();
submitData();
console.log("database", dataBase);
}
const submitData = () => {
let userObj = {
userName: newData.username,
password: newData.email,
id: newData.id
}
//it is showing undefined as you have not initialized database with any value, here an array
dataBase.push(userObj);
}
handleInputs();

Filtering Axios response

I'm trying to filter an axios response. My latest attempt the filter appears to be working, but my components aren't getting the expected data, only the correct # of records.
methods: {
loadItems() {
// Init variables
var self = this
var app_id = "ID";
var app_key = "KEY";
this.items = []
axios.get(
"https://api.airtable.com/v0/"+app_id+"/Pages",
{
headers: { Authorization: "Bearer "+app_key }
}
).then(function(response){
self.items = response.data.records.filter(item => item.fields.fxPage == 'TestPage');
response.data.records.map((item)=>{
return {
id: item.id,
...item.fields
}
})
}).catch(function(error){
console.log(error)
})
}
}
So close!
the .map() method returns a NEW array, so the map in that case is just returning and not getting used anywhere (e.g saving to a variable), what I would do would be to attach the map after the filter. e.g
self.items = response.data.record.filter(item => item.fields.fxPage === "TestPage").map(item => {
return {
id: item.id,
...item.fields
}
})
I hope this helps!

Jest - stub function within function

I'm writing unit-tests, where I need to set a mock response for a function within a function.
This is the function I want to mock:
cassandraDriver.js
module.exports = ({
cassandra_user,
cassandra_password,
cassandra_address
}) => {
if (!cassandra_address.length) throw Error('Cassandra address is not valid')
return new Promise((resolve, reject) => {
try {
const client = new driver.Client({
contactPoints: cassandra_address.split(','),
authProvider: authProvider(cassandra_user, cassandra_password),
queryconfig: {
consistency: driver.types.consistencies.quorum
}
})
return resolve(client)
} catch (e) {
reject(e)
}
})
}
This is the file that uses it:
const {
cassandraDriver
} = require('./lib')
module.exports = async ({
username = 'cassandra', //default values
password = 'cassandra', //default values
address,
keyspace,
replication_factor = 1,
migration_script_path,
logger = require('bunyan').createLogger({name: 'BuildCassandra'})
} = {}) => {
try {
const client = await cassandraDriver(username, password, address)
}).catch(err => {
throw Error(err)
})
} catch (e) {
logger.error(e)
throw e
}
}
How can I mock the call to 'cassandraDriver' in unit-tests? I tried using rewire, but the method is not exposed as it normally would be.
Thanks in advance.
let's modify your function so that it can accept a mock driver instead of cassandraDriver
const {
cassandraDriver
} = require('./lib')
module.exports = async ({
username = 'cassandra',
password = 'cassandra',
address,
keyspace,
replication_factor = 1,
migration_script_path,
logger = require('bunyan').createLogger({
name: 'BuildCassandra'
}),
driver = cassandraDriver
} = {}) => {
try {
const client = await driver(
username,
password,
address
})
} catch (e) {
logger.error(e)
throw e
}
}
(i also removed a superfluous .catch block)
next, you should create a "cassandra-driver-mock.js" which emulates the behaviour of the cassandra driver for your unit tests
the unit tests, of course, would pass the mock instead of the real driver as an option parameter
You can stub the module which exports cassandraDriver in your test file:
import cassandraDriver from "<path-to-cassandraDriver.js>";
jest.mock("<path-to-cassandraDriver.js>", () => jest.mock());
cassandraDriver.mockImplementation(() => {
// Stub implementation and return value
});
See Manual Mocks for more information.

Categories

Resources