Unit Test with Jest , Class constructor - class

How to test the following Class that has validation in construction using set.
const BaseParameter = class BaseParameter {
constructor(addr, fullname, value) {
this.addr = addr;
this.fullname = fullname;
this.value = value;
}
get value() {
return this._value;
}
set value(value) {
if (typeof value !== "number") {
throw new TypeError(`Parameter ${this.fullname} should be a number`);
}
this._value = value;
}
};
I have tried this following method of Jest.
test("BaseParameter with invalid constructor", () => {
expect(new BaseParameter("test", "test fullname", "a")).toThrowError(
TypeError
);
});
but throws the error and the pass fails.

The docs have clear example, I just has stuck
test("BaseParameter with invalid constructor", () => {
expect(() => new BaseParameter("test", "test fullname", "a")).toThrowError(
TypeError
);
});
https://jestjs.io/docs/en/es6-class-mocks

Related

Failed to add new elements when set initialState as an empty object

I try to use redux toolkit and I have this as menu-slice.js
I try to use property accessors to add a new property to fileItems, its initial value is an empty object.
import { createSlice } from "#reduxjs/toolkit";
const menuSlice = createSlice({
name: "ui",
initialState: {
fileItems: {},
},
reducers: {
setFileDate: (state, action) => {
state.FileDate = action.payload;
},
replaceFileItems: (state, action) => {
const filesList = action.payload.map((fileName) =>
fileName.slice(fileName.indexOf("/") + 1)
);
state.fileItems[state.FileDate] = filesList;
console.log(`filesList: ${filesList}`);
console.log(`state.fileItems: ${JSON.stringify(state.fileItems)}`);
console.log(`state.FileDate: ${state.FileDate}`);
state.fileContents = null;
},
I call dispatch with the api return value ( dispatch(menuActions.replaceFileItems(fileResponse.data));)
in menu-action.js:
the return value is an array of strings.
export const fetchFiles = (fileDate) => {
return async (dispatch) => {
const fetchFilesList = async () => {
const response = await fetch(
"some url" +
new URLSearchParams({
env: "https://env.com",
date: fileDate,
})
);
if (!response.ok) {
throw new Error("Fail to fetch files list!");
}
const data = await response.json();
return data;
};
try {
const fileResponse = await fetchFilesList();
dispatch(menuActions.setFileDate(FileDate));
dispatch(menuActions.replaceFileItems(fileResponse.data));
} catch (error) {
dispatch(
menuActions.showNotification({....
})
);
}
};
};
But it never prints console logs and didn't display where went wrong in the console or in the chrome redux extension.
I want to add data into state.fileItems on each click that triggers fetchFiles() when it returns a new array:
from state.fileItems = {}
check if state.fileItems already has the date as key,
if not already has the date as key,
change to ex: state.fileItems = {"2022-01-01": Array(2)}
and so on..
ex: state.fileItems = { "2022-01-01": Array(2), "2022-01-02": Array(2) }
I also tried to set state.fileItems as an empty array, and use push, but it didn't work either, nothing printed out, state.fileItems value was always undefined.
Can anyone please tell me why this didn't work?
Thanks for your time to read my question.

about vscode api for executeCommand("explorer.newFolder")

I want callback for after newFolder,
executeCommand("explorer.newFolder").then(value => console.log(value))
but The value is not the value of folderName.
I analyzed the code of the command you executed.
The explorer.newFolder command is defined as NEW_FOLDER_COMMAND_ID, and is connected with the openExplorerAndCreate handler. (The result is received through the handler of CommndsRegistry.)
The return of the openExplorerAndCreateis a callback function (Promise).
When i look closely inside,, if the input parameter is not isFolder, that is, if it is a file, a callback function is provided by the return commandService.executeCommand(NEW_UNTITLED_FILE_COMMAND_ID); command.\
but if it is a folder, there is no return value. That is undifined.
in vscode API documentation
return type of executeCommand() is Thenable<T | undefined>. That is, in the case of the corresponding command, it is returned as undefined, not Thenable<T>. If an error is not thrown and undefined is returned, it can be determined that it has been normally executed.
// src/vs/workbench/contrib/files/browser/fileAction.ts
...
export const NEW_FOLDER_COMMAND_ID = 'explorer.newFolder';
...
CommandsRegistry.registerCommand({
id: NEW_FOLDER_COMMAND_ID,
handler: async (accessor) => {
await openExplorerAndCreate(accessor, true);
}
});
...
async function openExplorerAndCreate(accessor: ServicesAccessor, isFolder: boolean): Promise<void> {
const explorerService = accessor.get(IExplorerService);
const fileService = accessor.get(IFileService);
const editorService = accessor.get(IEditorService);
const viewsService = accessor.get(IViewsService);
const notificationService = accessor.get(INotificationService);
const commandService = accessor.get(ICommandService);
const wasHidden = !viewsService.isViewVisible(VIEW_ID);
const view = await viewsService.openView(VIEW_ID, true);
if (wasHidden) {
// Give explorer some time to resolve itself #111218
await timeout(500);
}
if (!view) {
// Can happen in empty workspace case (https://github.com/microsoft/vscode/issues/100604)
if (isFolder) {
throw new Error('Open a folder or workspace first.');
}
return commandService.executeCommand(NEW_UNTITLED_FILE_COMMAND_ID);
}
const stats = explorerService.getContext(false);
const stat = stats.length > 0 ? stats[0] : undefined;
let folder: ExplorerItem;
if (stat) {
folder = stat.isDirectory ? stat : (stat.parent || explorerService.roots[0]);
} else {
folder = explorerService.roots[0];
}
if (folder.isReadonly) {
throw new Error('Parent folder is readonly.');
}
const newStat = new NewExplorerItem(fileService, folder, isFolder);
folder.addChild(newStat);
const onSuccess = async (value: string): Promise<void> => {
try {
const resourceToCreate = resources.joinPath(folder.resource, value);
await explorerService.applyBulkEdit([new ResourceFileEdit(undefined, resourceToCreate, { folder: isFolder })], {
undoLabel: nls.localize('createBulkEdit', "Create {0}", value),
progressLabel: nls.localize('creatingBulkEdit', "Creating {0}", value)
});
await refreshIfSeparator(value, explorerService);
if (isFolder) {
await explorerService.select(resourceToCreate, true);
} else {
await editorService.openEditor({ resource: resourceToCreate, options: { pinned: true } });
}
} catch (error) {
onErrorWithRetry(notificationService, error, () => onSuccess(value));
}
};
await explorerService.setEditable(newStat, {
validationMessage: value => validateFileName(newStat, value),
onFinish: async (value, success) => {
folder.removeChild(newStat);
await explorerService.setEditable(newStat, null);
if (success) {
onSuccess(value);
}
}
});
}

How to access Marshalling iOS [Nativescript]

I currently have a functional plugin, but I have a problem being able to get the object in the finishCheckout method
import { Options } from "./mercadopago-px.common";
import * as frameModule from "tns-core-modules/ui/frame";
export class LifeCycleProtocolImpl extends NSObject
implements PXLifeCycleProtocol {
public resolve: any;
public reject: any;
static ObjCProtocols = [PXLifeCycleProtocol]; // define our native protocalls
static new(): LifeCycleProtocolImpl {
return <LifeCycleProtocolImpl>super.new(); // calls new() on the NSObject
}
cancelCheckout(): () => void {
this.reject({
status: "cancel",
data: null,
error: "cancelCheckout"
});
return null;
}
changePaymentMethodTapped?(): () => void {
return null;
}
finishCheckout(): (result: PXResult) => void {
this.resolve({
status: "finishCheckout",
data: null,
error: null
});
return null;
}
}
export class MercadopagoPx {
public start(options: Options): Promise<any> {
return new Promise((resolve, reject) => {
let checkout = MercadoPagoCheckout.alloc().initWithBuilder(
MercadoPagoCheckoutBuilder.alloc()
.initWithPublicKeyPreferenceId(
options.publicKey,
options.preferenceId
)
.setLanguage(options.language)
);
let lifeCycleProtocolDelegate: LifeCycleProtocolImpl = LifeCycleProtocolImpl.new();
lifeCycleProtocolDelegate.resolve = resolve;
lifeCycleProtocolDelegate.reject = reject;
let pxLifeCycleProtocol: PXLifeCycleProtocol = lifeCycleProtocolDelegate;
checkout.startWithNavigationControllerLifeCycleProtocol(
frameModule.topmost().ios.controller,
pxLifeCycleProtocol
);
});
}
}
My custion is how to access here, actually not access because i have wrong with linter TS :
finishCheckout(): (result: PXResult) => void {
console.dir(result); <---- Here error, can't access to result
this.resolve({
status: "finishCheckout",
data: null,
error: null
});
return null;
}
Trying to access the object, I can not because it detects that the variable does not exist, when it is present, I do not know if it is the way to access the property, or if there is a way to access that object that returns the method to me which try to implement
It means you are returning a function from finishCheckout which has a parameter result.
finishCheckout(): (result: PXResult) => void {
console.dir(result); <---- Here error, can't access to result
this.resolve({
status: "finishCheckout",
data: null,
error: null
});
return null;
}
It suppose to be,
finishCheckout(result: PXResult) {
console.dir(result);
this.resolve({
status: "finishCheckout",
data: null,
error: null
});
return null;
}
if result should be a parameter for finishCheckout.
Edit:
As per the typings (finishCheckout(): (p1: PXResult) => void;), the method doesn't have a parameter but it returns a function that will have result as a parameter. Hence you can't access result in there.

Why TextDocumentContentProvider dont call provideTextDocumentContent on update when query params changes?

as title says, when i wanna update TextDocumentContentProvider with different query params by calling update method provideTextDocumentContent is not called...
only way i managed to get it working was with same URI as in calling
vscode.commands.executeCommand('vscode.previewHtml', URI, 2, 'Storybook');
relevant part of code:
// calculates uri based on editor state - depends on actual caret position
// all uris will start with 'storybook://preview'
function getPreviewUri(editor: vscode.TextEditor): vscode.Uri;
// transforms uri, so web server will understand
// ex: 'storybook://preview?name=fred' -> 'http://localhost:12345/preview/fred?full=1'
function transformUri(uri: vscode.Uri): vscode.Uri;
class StorybookContentProvider implements vscode.TextDocumentContentProvider
{
provideTextDocumentContent(uri: vscode.Uri): string {
var httpUri = transformUri(uri);
return `<iframe src="${httpUri}" />`;
}
onDidChange = new vscode.EventEmitter<vscode.Uri>();
update(uri: vscode.Uri) {
this.onDidChange(uri);
}
}
export function activate(context: vscode.ExtensionContext)
{
vscode.workspace.onDidChangeTextDocument(
(e: vscode.TextDocumentChangeEvent) => {
if (e.document === vscode.window.activeTextEditor.document) {
const previewUri = getPreviewUri(vscode.window.activeTextEditor);
provider.update(previewUri);
}
}
);
vscode.window.onDidChangeTextEditorSelection(
(e: vscode.TextEditorSelectionChangeEvent) => {
if (e.textEditor === vscode.window.activeTextEditor) {
const previewUri = getPreviewUri(vscode.window.activeTextEditor);
provider.update(previewUri);
}
}
);
const provider = new StorybookContentProvider();
context.subscriptions.push(
vscode.commands.registerCommand('extension.showStorybook', () => {
vscode.commands.executeCommand('vscode.previewHtml', vscode.Uri.parse('storybook://preview'), 2, 'Storybook')
}),
vscode.workspace.registerTextDocumentContentProvider('storybook', provider)
);
}

Babel: Replacing ArrowFunctionExpression vs FunctionDeclaration in ExportDefaultDeclaration

Say I have the following code I want to transform:
export default () => {};
The following visitor code works:
export default function ({ types: t }) {
return {
visitor: {
ArrowFunctionExpression(path) {
if (!path.node.body.directives.some(d => d.value.value === 'inject')) return;
path.node.body.directives = path.node.body.directives.filter(d => d.value.value !== 'inject');
path.replaceWith(t.arrayExpression([path.node]));
}
}
};
}
That results in the following output:
export default [() => {}];
Great! Now change the input:
export default function () {
'inject';
};
And the visitor:
export default function ({types: t}) {
return {
visitor: {
FunctionDeclaration(path) {
if (!path.node.body.directives.some(d => d.value.value === 'inject')) return;
path.node.body.directives = path.node.body.directives.filter(d => d.value.value !== 'inject');
path.replaceWith(t.arrayExpression([path.node]));
}
}
};
}
That produces the following error:
TypeError: unknown: Property elements[0] of ArrayExpression expected node to be of a type ["null","Expression","SpreadElement"] but instead got "FunctionDeclaration"
Okay, so convert the FunctionDeclaration to a FunctionExpression:
export default function ({types: t}) {
return {
visitor: {
FunctionDeclaration(path) {
if (!path.node.body.directives.some(d => d.value.value === 'inject')) return;
path.node.body.directives = path.node.body.directives.filter(d => d.value.value !== 'inject');
path.replaceWith(
t.arrayExpression([
t.functionExpression(path.node.id, path.node.params, path.node.body, path.node.generator, path.node.async),
])
);
}
}
};
}
And I get the following error:
TypeError: unknown: Property declaration of ExportDefaultDeclaration expected node to be of a type ["FunctionDeclaration","ClassDeclaration","Expression"] but instead got "ExpressionStatement"
And that is where I'm lost. I'm creating an ArrayExpression just as I was with the default-exported arrow function. Why is it complaining about receiving an ExpressionStatement?
Note, the desired output is as such:
export default [function () {
}];