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
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.
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 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?
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;
}
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);
};