I have node-fetch installed, but the rest of the files in the project aren't importing it and the tests for them aren't failing
import { IQuery } from 'models/IQuery.interface';
import { NextApiRequest, NextApiResponse } from 'next';
import { handleProxyResponse } from 'utils/handleProxyResponse.util';
import { appendApiRoute, getDefaultHeaders, getLocale } from 'utils/proxy.util';
export const getContentPage = async (locale: string, publicId: string) => {
const headers = getDefaultHeaders();
//fetch is undefined here
const response = fetch(appendApiRoute(`static-content/v1/${locale}/pages/${publicId}`), {
method: 'GET',
headers
});
return response;
};
export default async (request: NextApiRequest, response: NextApiResponse) => {
const currentLocale = getLocale(request);
const { query } = request;
const { slug } = query as IQuery;
const result = await getContentPage(currentLocale, slug);
return handleProxyResponse(result, response);
};
Failing test:
it('should return handledProxyResponse', async () => {
const result = await contentProxy(defaultRequest, response);
expect(result).toEqual(handleProxyResponseReturnValue);
});
May be it is a Issue of version. so you can try by use an external module
`npm install node-fetch`
then import it in your code
import fetch from "node-fetch"
Related
Im trying to dynamically load modules from a nitro server in a nuxt app, but I get the following error:
Cannot find module projectpath/.nuxt/services/listing imported from projectpath/.nuxt/dev/index.mjs
This is the snippet of code Im using for the handler where the dynamic import should take place:
export default defineEventHandler(async (event) => {
const { method, resource, paramValue } = parseRequestResource(event.node.req)
let ServiceInstance = services[resource]
if (ServiceInstance) {
return callResourceMethod(ServiceInstance, method, paramValue, event)
} else {
try {
ServiceInstance = await import(`../services/${resource}`)
} catch (error) {
const Proto = Object.assign({}, Service.prototype, { tableName: resource })
ServiceInstance = Object.create(Proto)
services[resource] = ServiceInstance
}
return callResourceMethod(ServiceInstance, method, paramValue, event)
}
})
How can I this to work? Is there some feature that nitro/nuxt have where I can do this?
I was able to achieve this functionality by using a nitro plugin. However the files being imported need to be *.mjs.
import fs from 'fs'
import { resolve } from 'path'
export default defineNitroPlugin(async (nitroApp) => {
const __dirname = resolve()
const servicesFolderPath = `${__dirname}/server/services`
const serviceFiles = fs.readdirSync(servicesFolderPath)
const services = {}
for (const fileName of serviceFiles) {
if (fileName == '__proto__.mjs') continue
try {
const moduleName = fileName.split('.')[0]
const module = await import(`${servicesFolderPath}/${fileName}`)
services[moduleName] = module.default
} catch (error) {
console.log(error);
}
}
nitroApp.$services = services
})
I have external .js file created exactly for fetching data from backend based on website locale. Here is the code:
import { ref } from "vue";
export function fetchData(section, key) {
// GET request using fetch with error handling and headers
const headers = {
method: "GET",
headers: { "Content-Type": "application/json" },
};
const fetchedData = ref(null);
fetch(
"http://localhost:4000/api/" + section + "/?api-key=" + key,
headers
)
.then(async (response) => {
const data = await response.json();
// check for error response
if (!response.ok) {
// get error message from body or default to response statusText
const error = (data && data.message) || response.statusText;
return Promise.reject(error);
}
fetchedData.value = data;
})
.catch((error) => {
console.error("There was an error!", error);
return error;
});
return fetchedData;
}
And this is code from .vue file where I calling fetchData function:
<script setup>
import { fetchData } from "../../utils/universal-fetch";
import { ref, watch } from "vue";
import { useStore } from "../../stores/language.js";
import { useI18n } from "vue-i18n";
import AOS from "aos";
const store = useStore();
const { locale } = useI18n({ useScope: "global" });
const fetchedData = ref(fetchData("homeFirstSection", store.getLanguage));
AOS.init();
watch(
() => locale.value,
() => {
fetchedData.value = fetchData("homeFirstSection", store.getLanguage);
}
);
</script>
When page is created/refreshed, fetchData function fetch data from backend correctly. The problem which I'm trying to solve is that, when I change a locale, watcher automatically detects that, locale was changed and variable fetchedData should be updated based on choosen locale.
Problem
Thanks!
I found a problem. Here is code:
export function async fetchData(section, key) { // Added async
// GET request using fetch with error handling and headers
const headers = {
method: "GET",
headers: { "Content-Type": "application/json" },
};
let fetchedData = null;
await fetch( // Added await
"http://localhost:4000/api/" + section + "/?api-key=" + key,
headers
)
.then(async (response) => {
const data = await response.json();
// check for error response
if (!response.ok) {
// get error message from body or default to response statusText
const error = (data && data.message) || response.statusText;
return Promise.reject(error);
}
fetchedData = data;
})
.catch((error) => {
console.error("There was an error!", error);
return error;
});
return fetchedData;
}
In my external .js file I was missing one more async await.
<script setup>
import { fetchData } from "../../utils/universal-fetch";
import { ref, watch } from "vue";
import { useStore } from "../../stores/language.js";
import { useI18n } from "vue-i18n";
import AOS from "aos";
const store = useStore();
const { locale } = useI18n({ useScope: "global" });
const fetchedData = ref(null);
fetchData("agreementsFirstSection", store.getLanguage).then(
(data) => (fetchedData.value = data)
); // Added .then
AOS.init();
watch(
() => locale.value,
() => {
fetchData("agreementsFirstSection", store.getLanguage).then(
(data) => (fetchedData.value = data)
); // Added .then instead of directly assign
}
);
</script>
And in .vue file I was missing .then insted of directly assigning value to variable. I added comments to code to compare changes before and after.
Problem solved
I am attaching all the function snippets below. I am using jest to run a unit test on this function but this needs to mock axios. I tried like this :
// TODO - mock axios class instance for skipped Test suites
describe("dateFilters()", () => {
beforeEach(() => {
jest.resetAllMocks();
});
it("Mock Fetch API for Date Options Response", async () => {
const mockFn = jest.fn();
setUpMockResponse(mockFn, mockFetchDateOptionsResponse);
const response = await dateFilters(Workload.WIN32);
expect(mockFn).toHaveBeenCalledTimes(1);
expect(response?.data).toEqual(mockFetchDateOptionsResponse);
});
});
The error I am getting is :
thrown: "Exceeded timeout of 5000 ms for a test.
Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."
It seems it is not mocking anything.
All the require function definitons are below:
export const dateFilters = async (platform) => {
const dates = await getKustoResponse({
queryName: platform.toLowerCase().concat("DateFilters"),
platform,
queryParams: {},
});
return dates;
};
export const getKustoResponse = async ({
queryName,
platform,
queryParams,
cluster = "Default",
}: QueryDetail) => {
const dbName = getClusterValue({ platform, cluster, key: "db" });
const url = getClusterValue({ platform, cluster, key: "kustoUrl" });
const postBody = {
db: dbName,
csl: queryParams
? substituteQueryParameters(queries[queryName], queryParams)
: queries[queryName],
};
const apiClient = ApiClient.getInstance();
const response = await apiClient.post(url, postBody, {
headers: {
...kustoApiRequestDefaultConfiguration.headers,
"x-ms-kql-queryName": queryName,
},
timeout: kustoApiRequestDefaultConfiguration.timeout,
});
return response;
};
import Axios, { AxiosInstance } from "axios";
import axiosRetry from "axios-retry";
export class ApiClient {
private static instance: AxiosInstance;
public static getInstance = (): AxiosInstance => {
if (!ApiClient.instance) {
ApiClient.createInstance();
}
return ApiClient.instance;
};
private constructor() {
ApiClient.getInstance();
}
protected static createInstance = () => {
const responseType = "json";
const client = Axios.create({
responseType,
});
axiosRetry(client, apiRetryConfiguration);
client.interceptors.request.use(requestInterceptor);
client.interceptors.response.use(responseInterceptor, errorInterceptor);
ApiClient.instance = client;
};
}
export const requestInterceptor = async (
request: AxiosRequestConfig
): Promise<AxiosRequestConfig> => {
const token = await getKustoToken();
request.headers = { ...request.headers, Authorization: `Bearer ${token}` };
return request;
};
There is no fetch call in your source code. Is it in the apiClient? If so, do this:
jest.spyOn(apiClient, 'post').mockImplementation();
expect(apiClient.post).toHaveBeenCalled();
I have a bit of code here that keeps failing due to Error: Fixture "activityLogPage" has unknown parameter "TestRailController", I am sure this is user error on my end but I cant quite figure it out. Below this is the TestRailController I am trying to call.
activitylogpage.ts --->
import { ActivityLogSelectors } from '../../specs/types/activityLog.type';
import { Page } from '#playwright/test';
import test from '../../common/testrail/fixtures';
export const activityLogSelectors: ActivityLogSelectors = {
datasource_id: 'label[for^=datasource_id]',
categories: 'label:has-text("Access Control: Authentication")',
policy: 'input[id^=downshift]',
};
type ActivityLogFixtures = {
activityLogPage: Page;
};
const activityLogTest = test.extend<ActivityLogFixtures>({
activityLogPage: async ({ page, TestRailController }, use) => {
TestRailController.startNewTest('1');
await page.goto('/');
await page.waitForURL(/risk-posture/i);
await page.click('a:has-text("Activity Log")');
await page.waitForSelector('text=Clear');
await use(page);
},
});
export default activityLogTest;
fixtures.js. --->
const base = require('#playwright/test');
const TestRailController = require('./testrail.interface.js');
module.exports = base.test.extend({
// https://playwright.dev/docs/test-advanced/#testinfo-object
testrailController: async ({ browser }, use, testInfo) => {
const testrailController = new TestRailController();
await use(testrailController);
for (const context of browser.contexts()) {
// eslint-disable-next-line no-await-in-loop
await context.close();
}
// only update testrail when process.env.APP_VERSION is valid string
// testInfo is needed here because this below part will be run before test started while testInfo is null
// use testrail feature for saving test-result
if (appVersion && testInfo) {
await testrailController.updateAllTests(testInfo);
} else {
console.log('Env var APP_VERSION or testInfo is not available, will not update testrail case');
}
},
});
I tried to run this code with npm start on terminal
//index.js
const api = require('./api');
console.log('Iniciando monitoramento!');
setInterval(async () => {
//console.log(await api.time());
console.log(await api.depth());
}, process.env.CRAWLER_INTERVAL);
//api.js
const axios = require('axios');
const queryString = require('querystring');
async function publicCall(path, data, method = 'GET', headers = {}) {
try {
const qs = data ? `?${queryString.stringify(data)}` : '';
const result = await axios({
method,
url: `${process.env.API_URL}${path}${qs}`
});
return result.data;
} catch (err) {
console.error(err);
}
}
async function time() {
return publicCall('/v3/time');
}
async function depth(symbol = 'BTCBRL', limit = 5) {
return publicCall('/v3/depth', { symbol, limit });
}
and my terminal display this error:
console.log(await api.depth());
^
TypeError: api.depth is not a function
at Timeout._onTimeout (C:\Users\mikae\Desktop\bot-criptomoedas\bot\index.js:6:27)
at listOnTimeout (node:internal/timers:557:17)
at processTimers (node:internal/timers:500:7)
I just want to run my aplication to send me informations about cryptocoins market. I'm using API from Binance.
You need to export the function.
export async function depth(symbol = 'BTCBRL', limit = 5) {
return publicCall('/v3/depth', { symbol, limit });
}
and then
import { depth } from '/.api'
Also update your package.json file to include.
"type": "module"
In the tutorial you linked you missed the 25th line:
module.exports = { time, depth }
Paste this in your app.js file and use this as import in index.js
const api = require('./api.js');