Stencil unit testing: How to mock initial state and load newSpecPage? - jestjs

I am new to unit testing and planning to write unit test cases but not E-2-E for the below mentioned scenario and playgrounnd link for scenario is at the bottom.
Scenario:-
I have a #State variable called "ifSuccessResponse" with initial value set as false.
When #State variable "ifSuccessResponse" is true, green-div loads.
When #State variable "ifSuccessResponse" is false, red-div loads.
How to mock initial state to have #State variable ifSuccessResponse to have value set as true and then load the newSpecPage so that I can test green-div is loaded.
Is it possible to update the #State variable ifSuccessResponse after loading the page in Moc Doc using newSpecPage . Curious to know whether we can do this like how we can do in enzyme library using setState method.
Playground-link:
https://webcomponents.dev/edit/Cbr1NS2QTrvC5scsmFZQ/src/index.stories.tsx

Instead of trying to mock State directly (by definition it is internal to component, otherwise you would/should use #Prop), you should find a way to get into the logic that exercise setting that state. Looking at the variable name, your component probably make call to some underlying API or service? If so, I would strongly recommend you to mock request/response to that service and then manipulate the State that way.
I use "fetch-mock" (https://www.npmjs.com/package/fetch-mock) to do this.
When you are using newSpecPage, you are dealing with DOM element so at that level, you want to minimize exposing internal logic like that so that you are actually testing how component is used. If you have complex logic, you could easily write unit test to test such function as well.

After creating the newSpecPage, you can access its contents. Try writing some console logs in your tests to see what you are working with.
For example:
console.log(page.root);
console.log(page.rootInstance);
console.log(page.root.outerHTML);
If you want to access or change a #State(), you can do that as follows
page.rootInstance.ifSuccessResponse = true
So the full test will look as follows
it('should show the green state', async () => {
const page = await newSpecPage({
components: [MyParentComponent],
template: () => <my-parent-component></my-parent-component>,
});
page.rootInstance.ifSuccessResponse = true;
const divEl = page.root.shadowRoot.querySelector('#green-div');
expect(divEl.innerHTML).toEqual('My favorite color is green');
});
Unfortunately I'm not able to run your playground project, so I hope I did it correctly. I also edited your test name slightly to make it a readable sentence. I would advise you to name your tests likewise.

Related

What are the risks involved in using custom decorators as validation pipes in Nestjs?

Background
A data structure in my database consists of "sections"; lists of custom objects. The number of sections may expand in the future, so to keep my code as DRY as possible, I wanted to determine the section to add/update/delete an item from to be defined dynamically as a parameter.
I quickly realised that doing something like #Body() section: SectionA | SectionB | SectionC... disables validation so I needed a single DTO Section that could encompass all sections. To do that I need to define dynamically which validators to apply as I have several #IsNotEmpty constraints.
So I came across this post whose selected answer recommends the usage of groups.
This posed the following challenges:
I now have to write a custom validation pipe. Relied heavily on this
I want to override the global validator pipe that I already had running and use my custom one for just that method. Outcome: didn't work, had to start defining the pipe on every controller method, a tradeoff I am willing to accept. Looks like there is no simple alternative.
However, I'm now faced with the final problem: how to use the parameters in the request to define these groups in the validator; another brick wall. No simple solution.
Solution
This question has been asked here but no satisfactory solution was actually given.
Option one recommended redefining the scope of the pipe to "request" level but didn't explain how, and solutions found online didn't work.
The second solution, using a custom decorator to perform the validation instead, did work, very well in fact here is a simplified version of the code:
export const ProfileSectionData = createParamDecorator(
async (data: unknown, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest();
let object = plainToInstance(SectionDto, request.body); // I don't need to access the metatype from the request because I know what type I need but I'm sure I could if need-be.
const groups = [request.params.profileSection];
let validatorOptions = { groups, ...defaultOptions };
const errors = await validate(object, validatorOptions);
if (errors.length > 0) {
throw new BadRequestException();
}
return request.body;
},
);
Implications?
Here's my question. When Jay McDoniel recommended using a custom decorator, they warn: "Do note, that this could impact how the ValidationPipe is functioning if that is bound globally, at the class, or method level."
What does this mean?
Are there any vulnerabilities or performance drawbacks associated with this solution?
Obviously, one drawback is that you are using validation outside a validation pipe which is not ideal from a point of view of order and single-responsibility but I can't think of tangible inconveniences beyond aesthetics and maintainability.
Knowing the background, would you have approached the problem in a completely different way?

Using Custom Functions with "I" in Page Object and Custom Helper in CodeceptJS

Hi CodeceptJS Community,
Is there a way to use custom defined functions (under steps_file.js) as I. customFunction() in page object files.
Is there a way to use native codeceptjs functions (like I.click()) in my custom helper files
I couldn't find any help in the documentation and in other sources. Is there any way to achieve this?
And is there any way to use xpath locators in puppeteer helper?
this.helpers['Puppeteer'].page.click(xpath);
I had the same problem to use custom steps in pageObjects.
To avoid it, i passed the actor (I) as parameter to my pageObject function.
page object:
const I = actor();
module.exports = {
doSomething(I){
I.login();
}
};
Test scenario:
Scenario('Test something' (I,pageObject)=>{
pageObject.doSomething(I)
})
In this case, pageObjects will has access to all custom steps from I :)
Thank you for your sharing Matheus. I have used a different solution. Instead of writing "I" object in every page object method (which was also one option for me), I have created a custom helper file and written all methods using puppeteer helper like below;
async method() {
await this.helpers['Puppeteer'].click(xpath);
}
I can call this method both in tests and page objects
I.method();
I was facing the same issue and when I looked into the typescripts definitions I noticed that actor() which is required in every page object etc. has custom steps arguments.
So this worked for me to extend the const I = actor(); witht the custom steps form steps_file.js;
const customSteps = require('./steps_file');
const I = actor(customSteps());
After that, I can use all methods in page objects like in tests scenarios which are accessing the methods from steps_file.js

xUnit for test DAL in .net core 2 and DI- a little bit of confusion

I a little bit of confusion about xUnit for test my DAL.
My goal is to verify that my DAL correctly accesses the DB and extract the right data.
I create a xUnit test project and try to do a simpli test with Moq like this
[Fact]
public void Test1()
{
// Arrange
var mockMyClass = new Mock<IMyClassBLL>();
// Setup a mock stat repository to return some fake data within our target method
mockStAverageCost.Setup(ac => ac.GetBy(It.IsAny<MyClassVO>())).Returns(new List<MyClassVO>
{
new MyClassVO { HCO_ID = "1"},
new MyClassVO { HCO_ID = "2"},
new MyClassVO { HCO_ID = "3"},
new MyClassVO { HCO_ID = "4"}
});
// create our MyTest by injecting our mock repository
var MyTest = new MyClassBLL(mockMyClass.Object);
// ACT - call our method under test
var result = MyTest.GetBy();
// ASSERT - we got the result we expected - our fake data has 6 goals we should get this back from the method
Assert.True(result.Count == 4);
}
The method above work fine.
Now I want access directly to the db for get data.
Obviously something escapes me, I did not understand how to perform a data test with .net core 2 simulating dependeny injection and accessing the data.
Can someone clarify my ideas?
Are you looking for a unit test or an integration test? They're fundamentally different things and serve different purposes.
If your goal is to ensure that GetBy (the unit of functionality under test) does what it's supposed to do, then you should not be using live data. A real connection with real data would introduce variables, causing the test to potentially fail when there's actually nothing wrong with GetBy. For a true unit test, you should only use mocks and test data.
If your goal is to ensure that your application can connect to your database and actually draw data out of it, then that's an integration test. You might potentially use GetBy/your repository, in general, in the test, but generally you'd want to avoid that. Again, connecting and querying directly with via something like ADO.NET serves to remove variables, so if the test fails, you'll know it was because there actually was a problem connecting/querying, in general, rather than just some issue with your repository or a particular method thereof.
Long and short, a good test tests just one thing. If that particular thing requires external components (such as a SQL Server database), then it's an integration test, and at that point, you're testing the integration of the component. Something like a repository method should not come into play, as that would be testing two different things in one test. If you need to test GetBy then there should be no external dependencies, such as a SQL Server database.
Additionally:
I did not understand how to perform a data test with .net core 2 simulating dependeny injection and accessing the data.
This would be an example of testing the framework, which is another no-no. You can safely assume that DI works in ASP.NET Core. It has its own test suite covering that. There is no need for you to add tests for that as well.

Proper use of artifacts.require?

I am trying to understand how artifacts.require should be used. I've seen the standard paragraph describing it as being for migrations and testing. From this I infer that the globally scoped artifacts with its method require are automatically defined by the truffle executable tool when doing migrations or running tests. However, I am working with some code that uses artifacts.require outside the context of any migrations or tests, rather, this code just needs to do the usual at and new. However, in this context, the object artifacts is not defined.
Do I have the right picture here? Is this an appropriate use of artifacts.require? If so, what must be done to make it be defined outside of migrations and testing?
Thanks for any suggestions!
artifacts.require really isn't meant to be used outside of a test. this is where it is defined: https://github.com/trufflesuite/truffle-core/blob/3e96337c32aaae6885105661fd1a6792ab4494bf/lib/test.js#L240
when in production code you should load the compiled contract into your application using truffle-contract https://github.com/trufflesuite/truffle-contract
here is a short example (from http://truffleframework.com/docs/getting_started/packages-npm#within-javascript-code and see
http://truffleframework.com/docs/getting_started/contracts#making-a-transaction )
var contract = require("truffle-contract");
var contractJson = require("example-truffle-library/build/contracts/SimpleNameRegistry.json");
var SimpleNameRegistry = contract(contractJson);
SimpleNameRegistry
.deployed()
.then(function(instance) {
return instance.setRegistry(address);
})
.then(function(result) {
// If this callback is called, the transaction was successfully processed.
alert("Transaction successful!")
})
.catch(function(e) {
// There was an error! Handle it.
});

CodedUI- Best way to create and use UIObject Repository( that requires minimum effort when UI changes)

I started working with CodedUI few months before to automate a desktop Application(WPF).
Just checking out for the best ways to create a framework for my Application.
As, I have seen in other automation tools, I feel the heart of an automation framework using any tool(UI Based) is the way it's object Repository is created i.e. how well the UI objects are defined. A Cleaner and well defined Object Repository always proves to be very helpful when it comes to updating your tests.
I am trying to discover the best way to store my UIObjects so that in case of any UI changes in my Application, I have to put minimum effort to update my automation test.
Also, If an Object changes in application, updating it only at one place should solve the problem.
This can be any kind of change like :
->change in just a property(This I feel would be very easy to update in automation Test. The best and Easiet way I feel is to simply update the .uitest file(the xml file) if possible.)
->change in hierarchy and position
->entirely new object added
For the 2nd and 3rd changes, updating scripts become a difficult job, esp if the UIObject is being referred at may places, in many TestMethods, or Modules.
Also, I have generally seen that in Test Methods, Variable Declarations are done to create a reference to the UIMap objects and those variables are further used in the TestMethod Code.
So, in this case If the UI of my application changes, I will have to update the variable decalaration in each of the Test Methods. I want to reduce this effort to changing the variable decalaration only at one place. OfCourse, I cannot have all the code inside only one Test Method. One way that came to my mind is as:
Can't I have simply one common place for all these Variable decalarations. We can give a unique and understandable name to each UIObject e.g.: The decalratoions will look like:
UITabPage UITabPage = this.UIMap.UISimWindow.UISelectEquipmentTabList.UITabPage;
WpfRow UIRow = this.UIMap.UISimWindow.UISelectEquipmentTabList.UITabPage.UIEquipmentDetailsTable.UIRow;
WpfText UIEquipmentTagText = this.UIMap.UISimWindow.UISelectEquipmentTabList.UITabPage.UIEquipmentDetailsTable.UIRow.UITagCell.UIEquipmentTagText;
WpfCheckBox UIEquipmentCheckBox = this.UIMap.UISimWindow.UISelectEquipmentTabList.UITabPage.UIEquipmentDetailsTable.UIRow.UICheckBoxCell.UICheckBox;
....
....
and use these variables wherever required. Hence, In case of any chnages also, there will be only one place where you will need to update thse objects.
But for this, These varaibles must be made STATIC. What can be problem with making these Object Variables static?
Please provide your suggestion on this topic. May be what I am thinking is not possible or practical. I just want to choose the best way to start with before I go too far with the automation scripts and realize later that my approach wasn't a good one.
Thanks in Advance,
Shruti
Look into using descriptive programming instead of using the UIMaps.
Make a static class with generic functions to assist. Going to give you some examples of how to set it up.
For example:
public WinWindow parentwin(string ParentControlName)
{
var parentwin = new WinWindow();
parentwin.SearchProperties.Add("Control Name", ParentControlName);
return parentwin;
}
public WinWindow childwin(string ChildWinControlName, string ParentControlName)
{
var childwin = new WinWindow(parentwin(ParentControlName));
childwin.SearchProperties.Add("Control Name", ChildWinControlName);
return childwin;
}
public WinButton button(string ButtonName,string ChildWinControlName, string ParentControlName)
{
var childwin = childwin(ChildWinControlName,ParentControlName);
var button = new WinButton(childwin);
button.SearchProperties.Add("Name", ButtonName);
}
public void ClickButton(string ButtonName,string ChildWinControlName, string ParentControlName)
{
var button = button(ButtonName,ChildWinControlName,ParentControlName);
Mouse.Click(button);
}
public void ChangeFocus(WinWindow NewFocus)
{
var NewFocus = new NewFocus();
NewFocus.SetFocus();
}
public void ChangeFocus(WinWindow NewFocusChild, string c)
{
var a = new NewFocus();
a.SetFocus();
}
ChangeFocus(childwin("WelcomeForm", "MainForm");
ClickButton("&OK", "WelcomeForm", "MainForm");

Resources