URLs should ends with the observation id in javascript - javascript

In total I have two files first one is tester and second is the solution for tester file
Here is my Tester File
const data = require('./data');
const result0 = data.results[0];
const { getTaxonPhotos } = require('./observations');
const isINaturalistPath = (pathname) =>
/(square.jpe?g|original.jpe?g|small.jpe?g|medium.jpe?g|large.jpe?g|_s.jpe?g)$/.test(pathname);
const hasIdQueryParam = (search) => /^\?\d+$/.test(search);
const isUrl = (url) => {
const { pathname, search } = new URL(url);
if (!isINaturalistPath(pathname)) {
throw new Error(`URL path doesn't look like an iNaturalist photo: ${pathname}`);
}
if (!hasIdQueryParam(search)) {
throw new Error(`URL origin doesn't have expected id on query string: ${search}`);
}
return true;
};
describe('Problem 06 - getTaxonPhotos() function', function () {
let sample, samples, sampleData;
beforeEach(() => {
sample = Object.assign({}, result0);
samples = [sample];
sampleData = { results: samples };
});
test('should return an Array of Objects with the right URLs', function () {
let result = getTaxonPhotos(sampleData);
expect(Array.isArray(result)).toBe(true);
expect(result.length).toBe(1);
const photos = result[0];
expect(isUrl(photos.square)).toBe(true);
expect(isUrl(photos.original)).toBe(true);
expect(isUrl(photos.small)).toBe(true);
expect(isUrl(photos.medium)).toBe(true);
expect(isUrl(photos.large)).toBe(true);
});
test('should return an empty Array if missing taxon', function () {
delete sample.taxon;
let result = getTaxonPhotos(sampleData);
expect(Array.isArray(result)).toBe(true);
expect(result.length).toBe(0);
});
test('real-data should produce the expected result', function () {
let result = getTaxonPhotos(data);
expect(Array.isArray(result)).toBe(true);
expect(result.length).toBe(9);
result.forEach((photos) => {
expect(isUrl(photos.square)).toBe(true);
expect(isUrl(photos.original)).toBe(true);
expect(isUrl(photos.small)).toBe(true);
expect(isUrl(photos.medium)).toBe(true);
expect(isUrl(photos.large)).toBe(true);
});
});
test('URLs should end with the observation ID on the query string', () => {
let taxonPhotos0 = getTaxonPhotos(data)[0];
let observationId = result0.id;
expect(taxonPhotos0.square.endsWith(`?${observationId}`)).toBe(true);
expect(taxonPhotos0.original.endsWith(`?${observationId}`)).toBe(true);
expect(taxonPhotos0.small.endsWith(`?${observationId}`)).toBe(true);
expect(taxonPhotos0.medium.endsWith(`?${observationId}`)).toBe(true);
expect(taxonPhotos0.large.endsWith(`?${observationId}`)).toBe(true);
});
});
Here is my solution for the tester file or you can say function to solve the tester code
function getTaxonPhotos(data) {
// TODO
let patt = /(http(s)?:\/\/)/
let arr = Array();
let pho_obj = {
original: "",
square: "",
small: "",
medium: "",
large: ""
};
data.results.forEach(function(element) {
if (element.hasOwnProperty('taxon') && element.taxon.default_photo) {
// Separate values and find url and id in them
let _values = Object.values(element.taxon.default_photo);
let _url = _values.find(sector => sector.match(patt));
let _id = _values.find( element => typeof element === 'number').toString();
let observationId = "1384377507";
// split the url before file extension
_url = _url.substring(0, (_url.indexOf(_id) + _id.length + 1));
// using a for loop with swith to make correct url
for (let i in pho_obj) {
switch (`${i}`) {
case "original":
pho_obj.original = _url + "original.jpg"+`?${observationId}`;
break;
case "square":
pho_obj.square = _url + "square.jpg"+`?${observationId}`;
break;
case "small":
pho_obj.small = _url + "small.jpg"+`?${observationId}`;
break;
case "medium":
pho_obj.medium = _url + "medium.jpg"+`?${observationId}`;
break;
case "large":
pho_obj.large = _url + "large.jpg"+`?${observationId}`;
break;
}
}
arr.push(pho_obj);
}
});
return arr;
}
I successfully completed 3 conditions but 1 last goes wrong can you help me solve this (I test using jest in javascript)
√ should return an Array of Objects with the right URLs (3 ms)
√ should return an empty Array if missing taxon
√ real-data should produce the expected result (5 ms)
× URLs should end with the observation ID on the query string (3 ms)

let taxonPhotos0 = getTaxonPhotos(data)[0];
I don't think you have anything define for data
did you try
let taxonPhotos0 = getTaxonPhotos(sampleData)[0];

Related

Convert iterative function to recursive kind using javascript

I have written a function to pull stream data from the fetch API. I want to convert the function to a recursive one and would like to write it as an async function.
Here is the code which works but not asynchronous:
const productsStream = async () => {
const request = {
searchRange: ['fragrance', 'perfumery', 'cologne'],
exclusionCategory: ['discounted']
}
const response = await fetch('/products/stream', {
method: 'POST',
body: JSON.stringify(request)
});
const decoder = new TextDecoderStream();
const reader = response.body.pipeThrough(decoder).getReader();
let line = "";
while (true) {
const { done, value } = await reader.read();
let chunk = remainder + value;
let products = []
let newlineIndex;
while ((newlineIndex = chunk.indexOf("\n")) != -1) {
let item = chunk.substring(0, newlineIndex);
chunk = chunk.substring(newlineIndex);
if (chunk.length > 1) chunk = chunk.substring(1);
}
line = chunk;
products = []
if ( done ) break;
}
}
I'd welcome any help in converting this.

Function B returns null when called from function A, but returns correct value when logged within function B

please refer to the code below:
function getGdriveLinks() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName('Test');
const fileNames = sheet.getRange('C2:C').getValues();
const mainFolder = DriveApp.getFolderById('Folder ID');
for (var i = 0; i < fileNames.filter(String).length; i++){
var fileName = fileNames[i][0].toString();
var fileLink = getGdriveLink(fileName,mainFolder);
Logger.log(fileLink);
}
}
function getGdriveLink(searchFileName,folder){
var mainFiles = folder.getFiles();
while (mainFiles.hasNext()){
var file = mainFiles.next();
if(file.getName().indexOf(searchFileName) != -1){
Logger.log(file.getUrl());
return file.getUrl();
}
}
var subFolders = folder.getFolders();
while (subFolders.hasNext()){
var subFolder = subFolders.next();
getGdriveLink(searchFileName,subFolder);
}
}
Basically, the aim is to get the filenames in C2:C of Test sheet, find each of these in the 'Folder ID', and then return their URL. The URL is returned correctly when I log it from getGdriveLink(searchFileName,folder) using Logger.log(file.getUrl()). However, it returns null via the Logger.log(fileLink) when the result goes back to getGdriveLinks() function. Is there anything I'm missing? We're using a corporate domain if that's something to consider. Hoping for your guidance. Thanks!
You could also do it this way and avoid recursion altogether
function getPathAllDrivesFromId(fileid) {
var ids = [{id:fileid,name:DriveApp.getFileById(fileid).getName()}];
let r;
do {
r = Drive.Files.get(fileid,{supportsAllDrives:true,supportsTeamDrives:true});
if(r.parents.length > 0) {
//Logger.log(JSON.stringify(r.parents[0]));
ids.push({id:r.parents[0].id,name:DriveApp.getFolderById(r.parents[0].id).getName()});
fileid = r.parents[0].id
}
}while (r.parents.length > 0);
if(ids[ids.length - 1].name == "Drive") {
ids[ids.length - 1].name = Drive.Drives.get(ids[ids.length - 1].id).name;
}
//Logger.log(JSON.stringify(ids));
let path = ids.map(obj => obj.name).flat().reverse().join(' / ')
//Logger.log(path);
return path;
}
function getGdriveLinks() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('Test');
const osh = ss.getSheetByName("Results");
const ns = sh.getRange('C2:C' + sh.getLastRow()).getValues();
const folder = DriveApp.getFolderById('Folder ID');
const result = [["Filename", "Id", "Url", "path"]];
ns.forEach(n => {
let files = DriveApp.getFilesByName(n);
while (files.hasNext()) {
let file = files.next();
let path = getPathAllDrivesFromId(file.getId());
if (~path.indexOf(folder.getName())) {
result.push([file.getName(), file.getId(), file.getUrl(), path]);
}
}
})
osh.clearContents();
osh.getRange(1, 1, result.length, result[0].length).setValues(result);
}

Loop over a list of ids and foreach id get data from api

Loop over a list of ids and foreach id get data from api but, i can make only 40 requests per 10 seconds, i'm getting data from tbdb but i'm getting kicked by the api here is my code
Popular.findAll({ limit: 25 }).then((filmes) => {
for (let index = 0; index < filmes.length; index++) {
const element = filmes[index];
const id_filme = element.id_filme;
i get each movie id so i can make requests to the api with this function..
function fetchdata(id_filme) {
setTimeout(function () {
axios
.all([
axios.get(
`https://api.themoviedb.org/3/movie/${id_filme}?api_key=${process.env.API_KEY}&language=pt-BR`
),
axios.get(
`https://api.themoviedb.org/3/movie/${id_filme}/videos?api_key=${process.env.API_KEY}&language=pt-BR`
),
])
.then(
axios.spread(function (detalhes, linksyt) {
var filme = detalhes.data;
var youtube = linksyt.data;
// console.log(filme, youtube);
var filmesLista = new Array();
const title = filme.title;
const filmeid = filme.id;
if (Object.keys(filme.genres).length === 0) {
var genre = filme.genres;
} else {
var genre = filme.genres[0].name;
}
const overview = filme.overview;
const poster_path =
"https://image.tmdb.org/t/p/w500" + filme.poster_path;
const release_date = filme.release_date;
const vote_average = parseFloat(filme.vote_average);
const backdrop_path =
"https://image.tmdb.org/t/p/original" + filme.backdrop_path;
const imdb_id = filme.imdb_id;
const runtime = filme.runtime;
if (Object.keys(youtube.results).length === 0) {
var trailer = "";
} else {
var trailer =
"http://www.youtube.com/watch?v=" + youtube.results[0].key;
}
filmesLista.push([
filmeid,
title,
genre,
overview,
poster_path,
release_date,
vote_average,
backdrop_path,
imdb_id,
runtime,
trailer,
]);
console.log(filmesLista);
filmesLista.forEach((i) => {
const filmeid = i[0];
const title = i[1];
const genre = i[2];
const overview = i[3];
const poster_path = i[4];
const release_date = i[5];
const vote_average = i[6];
const backdrop_path = i[7];
const imdb_id = i[8];
const runtime = i[9];
const trailer = i[10];
Detalhes.create({
id_filme: `${filmeid}`,
title: `${title}`,
genre: `${genre}`,
release_date: `${release_date}`,
vote_average: `${vote_average}`,
imdb_id: `${imdb_id}`,
runtime: `${runtime}`,
overview: `${overview}`,
poster_path: `${poster_path}`,
backdrop_path: `${backdrop_path}`,
trailer: `${trailer}`,
});
});
})
);
o++;
if (o < 25) {
fetchdata(id_filme);
}
}, 10000);
console.log("INSERIDO NO BANCO");
}
fetchdata(id_filme);
the code works but, works so fast and i get kicked every time i run with more than 40 ids.. i'm strugling on just make 40 request every 10 secconds. anyone can help me please?

In the Flexsearch Library, How to search all matching text?

I have a large text with 10 "hell" words in the document, and I want flexSearch to retrieve all the matches in the full text for me. I currently use the index. search method, but it can only retrieve the first hell, not include the rest. I don't know what's going on.
my core code:
import Flexsearch from "flexsearch";
//英文搜索
const searchENOptions = {
encode: "icase",
tokenize: "reverse",
resolution: 9,
doc: {
id: "key",
field: ["content"],
},
};
this.indexEN = new Flexsearch(searchENOptions);
const { pages } = this.$site;
this.indexEN.add(pages);
const query = this.query.trim().toLowerCase(); // query keywords
let result = null;
if (!query) {
return;
}
const regex = /[\x00-\x7F]/g;
// currently, the result only has one item.
result = this.indexEN.search(query).map((page) => {
return {
...page,
text: this.getSuggestionText(page),
};
});
}
function getSuggestionText(page) {
const content = page.content; // fullText
const queryIndex = content
.toLowerCase()
.indexOf(this.query.toLowerCase());
const queryFirstWord = this.query.split(" ")[0];
let startIndex =
queryIndex === -1
? content.toLowerCase().indexOf(queryFirstWord.toLowerCase())
: queryIndex;
let prefix = "";
if (startIndex > 15) {
startIndex -= 15;
prefix = "... ";
}
const text = page.content.substr(startIndex, SEARCH_RESULT_LENGTH);
return highlightText(text, this.query) + prefix;
}

Javascript - can't iterate over object in incremental search

I'm very new to javascript/dev so I hope there is a an obvious solution that I've not thought of. My code returns search items from TVMaze.com API. The feature giving me trouble is the incremental search (as a user types in input box, the code returns and displays images by creating a new div and appending images, removing and replacing the an div).
My problem is that on deleting all characters from input box, I receive the error: "Uncaught (in promise) TypeError: shows is not iterable" which I suppose means that there is no object to iterate over? Thanks in advance for any help.
const input = document.querySelector("#query");
input.addEventListener("input", async function (e) {
e.preventDefault();
const searchTerm = e.target.value;
const config = { params: { q: searchTerm } };
const res = await axios.get(`http://api.tvmaze.com/search/shows?`, config);
makeImages(res.data);
clearList();
});
const makeImages = (shows) => {
const div = document.createElement("div");
for (let result of shows) {
if (result.show.image) {
const img = document.createElement("IMG");
img.className += "resultImage";
img.src = result.show.image.medium;
const title = document.createElement("h3");
title.className += "resultTitle";
title.innerText = result.show.name;
const year = document.createElement("h4");
year.className += "score";
year.innerText = result.show.premiered;
var sub = year.innerText.substring(0, 4);
var yearNum = parseInt(sub);
div.append(year);
div.append(img);
div.append(title);
document.body.appendChild(div);
}
if (yearNum <= 2000) {
var retro = document.createElement("h5");
retro.className = "retro";
retro.innerText = "retro";
div.append(retro);
}
}
};
let clearList = () => {
var allImg = document.querySelectorAll("IMG");
if (allImg.length === 0) {
document.createElement("div");
return makeImages();
}
var oldDiv = document.querySelector("div");
oldDiv.remove();
console.log(oldDiv);
};

Categories