Pre-request script code repository - postman

Is it possible to store common javascript functions centrally for use in pre-request script?
In a "Postman Run" with several separate api calls I need to generate a new datetimeoffset for each call. Currently, I copy the getDateTimeOffSet javascript function to the "pre-request script" tab of each call.
Ideally I would have a central place to store helper function and be able to call these functions from the individual pre-request scripts.

Unfortunately, the only way to re-use function in postman - is to store them as a global/environment variable. You may try to create a separate request and initiate some kind of utils module and then add it to the scope of your variables:
pm.environment.set('utils', () => {
const generateRandomText = () => {
//generate random text
}
const generateUsername = () => {
//generate username
}
return {
testPackage: {
generateRandomText,
generateUsername
}
};
});
In Pre-request scripts and Tests of other request you can simply call:
const utils = eval(environment.utils)();
const text = utils.testPackage.generateRandomText();
const username utils.testPackage.generateUsername();

Related

How to run a single test suite in Jest?

I have many test suites. I wanna to run a singe one and skip all the others, and I would like to do this on the code level.
I know I can do this using .only() and .skip() in a test file, but that supports only the tests / describes defined in that file.
Is there a way to do this globally? Like is there something like .only() which - when called on the top level describe - runs only that test suite and all others are skipped?
Or: when called on a single test ( it().only() ), then only that test runs and nothing else?
I see nothing like this in the API, but maybe Jest can be configured to work this way?
Is this possible with Jest or is this something I can only do via CLI?
If I understand correctly: You want to run just one test suite/file.
You can do this from the command line with jest path/to/filename.test.js.
Within a file, you can use test.only(name, fn, timeout) to only run that test. This won't stop Jest from moving on to the next testing file though.
Full Jest CLI docs
As far as I am aware, you cannot do this from within the test file itself.
The closest I can think of would be to set the `testmatch' in Jest's config to a pattern that only matches the file(s) you want run.
package.json
{
"name": "my-project",
"jest": {
"testmatch": "**/my.test.js"
}
}
I think if you adapt this answer: https://stackoverflow.com/a/59487370/14553660 it should give you what you need.
For example:
testsuite.test.js
import { signuptests } from './signup.test.js'
import { logintests } from './login.test.js'
import { logouttests } from './logout.test.js'
describe('Signup', signuptests)
describe.only('Login', logintests)
describe('Logout', logouttests)
signup.test.js
export const signuptests = () => {
it('Should have login elements', () => {});
it('Should Signup', () => {}});
}
login.test.js
export const logintests = () => {
it.only('Should Login', () => {}});
it('etc',()=>{});
}
logout.test.js
export const logouttests = () => {
it('Should Logout', () => {}});
it('etc',()=>{});
}
You will be able to use .only at the top level - in the testsuite file - to determine which test files are run, and you can also use .only within each individual test file (e.g. within login.test.js) to only run one particular test from that file.
I don't know that there is a limit to nesting describe blocks, so I imagine you could even make a 'master-testsuite' that imports different testsuites (which in turn import different test files...etc)

How to get extensionContext in vscode extension unit test?

Currently I am writing unit tests about vscode extension. But some functions are using extensionContext and I can't get extensionContext in unit tests. Any way to get it?
Just came across this question, because I had exactly the same problem.
It looks like you can do the following in a test:
const ext = vscode.extensions.getExtension("publisher.extensionName");
And you can return anything from your activate function, so you could decide to return the extension context (or anything else that you need) there:
export async function activate(
context: vscode.ExtensionContext
): Promise<vscode.ExtensionContext> {
// Your activation code...
return context;
}
And then you can access the context in the test:
const ext = vscode.extensions.getExtension("publisher.extensionName");
const myExtensionContext = await ext.activate();
You find publisher.extensionName information in package.json of the extension:
{
"publisher": "myself",
"name": "myextension",
"displayName": "My Extension",
"description": "",
"version": "1.0.0",
...
Another idea is to add a command that returns the context:
export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(vscode.commands.registerCommand('getContext', () => context));
}
and then get the context by:
const context = await vscode.commands.executeCommand("getContext") as vscode.ExtensionContext;
But be careful not to expose the context in production
This is an answer to an old question, but I've had the same problem and I'm answering it now, so others can see it.
I found this solution in https://github.dev/microsoft/vscode extensions/vscode-api-test/src/extension.ts and extensions/vscode-api-test/src/singlefolder-test/state.test.ts files.
First, the context entered in the activate function must be registered in the global as shown below.
import * as vscode from 'vscode';
export function activate(_context: vscode.ExtensionContext) {
// Set context as a global as some tests depend on it
(global as any).testExtensionContext = _context;
}
After that, you can use it as follows in the file to be tested.
import * as assert from 'assert';
import 'mocha';
import { ExtensionContext, extensions } from 'vscode';
suite('vscode API - globalState / workspaceState', () => {
let extensionContext: ExtensionContext;
suiteSetup(async () => {
// Trigger extension activation and grab the context as some tests depend on it
await extensions.getExtension('vscode.vscode-api-tests')?.activate();
extensionContext = (global as any).testExtensionContext;
});
test('state', async () => {
// Do some tests here using extensionContext
}
});
});
In the signature of the activate function, context is received as a parameter, but I don't know why, but here it can be used without setting context as a parameter. It may be that the corresponding value is entered automatically.

Navigation Unit Testing in MvvmCross

Trying to unit test the navigation in one of my command calls into a private method. Just trying to test if the navigation request has been made as a result of this command execution.
There's the old documentation;
https://www.mvvmcross.com/documentation/fundamentals/testing
This documentation does not factor in new async based calls as far as I found; For example IMvxMainThreadAsyncDispatcher
Either we need to implement two ExecuteOnMainThreadAsync methods or inherit from MvxMainThreadAsyncDispatcher in MockDispatcher.
Also need to add IMvxMainThreadAsyncDispatcher in IoC registration.
var mockDispatcher = new MockDispatcher();
...
...
Ioc.RegisterSingleton<IMvxMainThreadAsyncDispatcher>(MockDispatcher);
So almost all tests work except navigation call requests. Below method inside MockDispatcher never gets called so I can't check request counts;
public async Task<bool> ShowViewModel(MvxViewModelRequest request)
{
Requests.Add(request);
return true;
}
Anybody has a working code that would mock and gets this Request called or in some other form? IMvxMainThreadDispatcher is being set as absolute, and navigation calls are not done with ShowViewModel<>() anymore in MVVMCross, it's done by calling navigationService.Navigate();
Well, I have found the solution to my question... The ShowViewModel is called when navigation service is properly mocked. I have found a piece of code on GitHub from MvvmCross's own repo on how they do tests for navigation. My next challenge would be to mock the destination viewModel but that's separate and below code doesn't cover that. Previously I had a very basic IMvxNavigationService mock.
var mockLocator = new Mock<IMvxViewModelLocator>();
mockLocator.Setup(
m => m.Load(It.IsAny<Type>(), It.IsAny<IMvxBundle>(), It.IsAny<IMvxBundle>(), It.IsAny<IMvxNavigateEventArgs>())).Returns(() => new FakeViewModel());
mockLocator.Setup(
m => m.Reload(It.IsAny<IMvxViewModel>(), It.IsAny<IMvxBundle>(), It.IsAny<IMvxBundle>(), It.IsAny<IMvxNavigateEventArgs>())).Returns(() => new FakeViewModel());
var mockCollection = new Mock<IMvxViewModelLocatorCollection>();
mockCollection.Setup(m => m.FindViewModelLocator(It.IsAny<MvxViewModelRequest>()))
.Returns(() => mockLocator.Object);
Ioc.RegisterSingleton(mockLocator.Object);
var loader = new MvxViewModelLoader(mockCollection.Object);
_navigationService = new MvxNavigationService(null, loader)
{
ViewDispatcher = MockDispatcher,
};
_navigationService.LoadRoutes(new[] { typeof(YourViewModelTestClass).Assembly });
Ioc.RegisterSingleton<IMvxNavigationService>(_navigationService);

postman dynamic unset environment variables

Is there a way to unset environment variables dynamically?
I would like to access the environment vars and do a find & replace/delete action so I can test more dynamically.
For instance, say I want to test the creation of users, I create vars like {{tmp-username}}, {{tmp-email}}, etc... replace them with other values for the next test and remove them when I'm done.
I would do a stringsearch on tmp- if I knew how to access these using code...
Thanks in advance for any reply
To clarify, this question is different: Postman: How to delete/clear postman environment variable at run-time
This deals with knowing the exact name of the var you wish to unset. I want to search or iterate trough the vars to remove or edit them.
Could you use a function in the Tests tab to iterate through the variables and clear them out after the last test had run?
For example:
function cleanup() {
const clean = _.keys(pm.environment.toObject())
_.each(clean, (arrItem) => {
pm.environment.unset(arrItem)
})
}
cleanup()
This wouldn't 'replace' the values but this would give you confidence that the ones that are set during the run are not being used again.
EDIT
If you wanted to clear out a specific set of variables, ones that you have given a certain prefix, you could use this:
function cleanup() {
const clean = _.keys(pm.environment.toObject())
_.each(clean, (arrItem) => {
if (arrItem.startsWith("tmp")) {
pm.environment.unset(arrItem)
}
})
}
cleanup()
If you want to see all the keys and the values you could use this to log them to the console:
_.map(pm.environment.toObject(), (value, key) => console.log(`The key is '${key}' and the value is '${value}'`))

How to access global constant in unit tests with Jest?

I want to mock a global variable and test if it has been called in my function. In my file, I define a global variable "remote" which instanciates a Subject (RxJS library). I just want to test if the next function of Subject has been called with the right parameter "name". However, I can't access the global variable remote in my test file. I tried to mock it in my setup file, but doesn't work.
How can I do that ?
const remote = new Subject();
const analytics = {
click: (name) => {
if (name) {
remote.next(name);
}
}
}
module.exports = analytics;
Thanks !
This is a good question. When you use webpack, your individual file is wrapped into different function call. Check out this doc.
The best part of this question is that it shows the necessity of IOC/DI if you want your code to be testable. Instead of defining remote in your local module, you can export an Analytics class and then inject remote to its constructor.
// Analytics.js
export default class Analytics{
constructor(remote) {
this.remote = remote
}
click(name) {
if (name) {
this.remote.next(name)
}
}
}
main.js
import Analytics from './Analytics'
const remote = new Subject()
const analytics = new Analytics(remote)
analysis.click('foo')
It would be tedious to inject dependencies to all components/services. Angular has an decent doc on why/how to simplify it. Hope this is helpful!
// Update
You can use window to define global constant and access it in tests by using window.remote
const remote = new Subject()
window.remote = remote
When you want to mock remote, remember to modify its properties rather than the reference to it.
// test.js
beforeEach(() => {
// wrong !!!
window.remote = {
next(name) { assert(name) }
}
// right
window.remote.next = name => assert(name)
})