I use veevalidate rule for each input in my form. After submit with valid data, all these data have been sent successfully to backend-side, but on frontend-side each input is highlighted as it ivalid.
I had added reset method from veevalidate to unset any errors when submit is selected. But it don't work. Here is the part of my code
beforeSubmit() {
this.$validator.pause();
this.$nextTick(() => {
this.$validator.errors.clear();
this.$validator.fields.items.forEach(field =>
field.reset());
this.$validator.fields.items.forEach(field =>
this.errors.remove(field));
this.$validator.resume();
});
this.$validator.validateAll().then((result) => {
this.onSubmit();
...
I came to solution: when all errors have been removed from the form in next render with $nextTick, we should replace this.$validator.resume() method with this.$validator.reset(). Thant's it.
In general, the working part is
beforeSubmit() {
this.$validator.pause();
this.$nextTick(() => {
this.$validator.errors.clear();
this.$validator.fields.items.forEach(field =>
field.reset());
this.$validator.fields.items.forEach(field =>
this.errors.remove(field));
this.$validator.reset();
});
this.$validator.validateAll().then((result) => {
this.onSubmit();
...
Related
When creating kendo ui Javascript template and using a form layout, adding a DropDownList with server filtering set to true , kendo ui will throw an "invalid template " error.
While setting the server filtering to false it will work as expected
Sample code
https://github.com/Elrashid/TelerikAspNetCoreApp.tiket.2022121901
compiled code
https://github.com/Elrashid/TelerikAspNetCoreApp.tiket.2022121901/releases/download/202211219194020/publish-self-contaned.zip
Tested Scenarios:
✔DropDownList with ServerFiltering trueinside Kendo Tempate will work
✔DropDownList with ServerFiltering false will was a Form Layout Editer inside Kendo Tempate will work
❌DropDownList with ServerFiltering true will was a Form Layout Editer inside Kendo Tempate will not work
Error :
[](https://i.stac> k.imgur.com/nULHE.png)
Error Code :
#(Html.Kendo().Form()
.Name("Biblio_Form")
.HtmlAttributes(new { action = "Biblio_Save", method = "POST", })
.Layout("grid")
.Grid(g => g.Cols(1).Gutter(10))
.Validatable(v =>
{
v.ValidateOnBlur(true);
v.ValidationSummary(vs => vs.Enable(false));
})
.Items(items =>
{
items.Add()
.Field(f => f.BiblioId)
.Label(l => l.Text("Biblio Id"))
.Editor(e =>
{
e.DropDownList()
.HtmlAttributes(new { })
.DataTextField("Title")
.DataValueField("BiblioId")
.NoDataTemplate("nodata")
.Filter(FilterType.Contains)
.DataSource(source =>
{
source.Read(read =>
{
read.Action("biblio_read", "Home");
})
.ServerFiltering(true);
});
});
}).ToClientTemplate())
Explicitly call the .ToClientTemplate() configuration method.
Addunique identifier thru .Name() configuration option.
this will have to be doen even if you call.ToClientTemplate() on the parent , so you have to call it for the children also
<script type="text/x-kendo-template" id="...........">
#(Html.Kendo().Form<Biblio>()
.Name("Biblio_Form")
....
.Items(items =>
{
items.Add()
.Field(f => f.BiblioId)
.Label(l => l.Text("Biblio Id"))
.Editor(e =>
{
e.DropDownList()
.Name("serverFilteringTrue")
.DataTextField("Title")
.DataValueField("BiblioId")
.Filter(FilterType.Contains)
.DataSource(source =>
{
source.Read(read =>
{
read.Action("biblio_read", "Home");
})
.ServerFiltering(true);
}).ToClientTemplate();
});
}).ToClientTemplate())
</script>
Ref.
[ASP.NET Core Data Grid Component Client Detail Templates - Telerik UI for ASP.NET Core]
(https://docs.telerik.com/aspnet-core/html-helpers/data-management/grid/templates/client-detail-template)
I need to take a value from a table that changes after every page refresh. For example CPU for Chrome
describe('test dynamic table and check Chrome CPU', () => {
it('passes', () => {
cy.visit('some url')
cy.contains('span', 'CPU')
.parent()
.within(() => {
cy.contains('[role=cell]', 'Chrome')
})
})
})
Table:
UPDATE:
FYI
After refreshing the page, you will get columns and row changing place:
enter image description here
You can do like this:
cy.contains('span', 'Chrome')
.parent()
.within(() => {
cy.contains('[role=cell]', '%')
.invoke('text')
.then((text) => {
cy.log(text) //Logs 8.3%
//removing % and converting into number and asserting
expect(+text.replace(/%/g, '')).to.be.greaterThan(5)
expect(+text.replace(/%/g, '')).to.be.lessThan(15)
expect(+text.replace(/%/g, '')).to.eq(8.3)
})
})
I have an array of messages containing some text and an inline keyboard with "delete" button.
bot.command('items', ctx => {
items.forEach(async data => {
await ctx.reply(data.Title,
Markup.inlineKeyboard([Markup.button.callback("delete item", "DeleteItem")]));
})
})
And I have a function bot.action for the delete buttons on my inline keyboard. How do I pass a parameter to the bot.action so I can delete the item via the delete button.
bot.action("DeleteItem", async ctx => {
ctx.reply("deleting item");
})
For delete message, you can use:
bot.action('delete', ctx => ctx.deleteMessage())
As you can see from examples/echo-bot-module.js.
If you need pass a parameter to the bot.action, you may try:
bot.action(/^data-(\d+)$/, (ctx) => {
return ctx.answerCbQuery(`Param: ${ctx.match[1]}! 👍`)
})
// And send with callback data
Markup.button.callback('Button', `data-${Math.round(Math.random()*1000)}`)
I have a Grid component which includes 24 divs and inside of each div I need to take the value.
This value actually arrives in <p>, so which is the best way to do this?
Below is the app image. I would appreciate an example.
You could probably do something like storing the data in an object or array outside of the Cypress chain. Without a code example, here's my best guess.
cy.get('grid').within(() => { // cy.within() searches only within yielded element
const data = {}; // create data object
cy.get('div').each(($div, index) => { // cy.each() allows us to iterate through yielded elements
data[index] = $div.text() // or possibly some other JQuery command to get the value
// additionally, could go without the index at all and make `data` an array.
}).then(() => {
// whatever needs to be done with `data`, wrapped in `then` to make sure data is populated correctly.
});
});
You can add use each for this to loop through the elements and then do further operations:
cy.get('.chakra-stack')
.find('p')
.each(($ele) => {
cy.log($ele.text().trim()) //Logs all the texts one by one
})
Just add the p selector to your cy.get() command
cy.get('div.chakra-stack p') // access <p> within <div>
.each($el => {
cy.wrap($el).invoke('text')
.then(text => {
...
})
})
To get the value before the text
cy.get('div.chakra-stack p') // access <p> within <div>
.each($el => {
cy.wrap($el)
.prev() // element with value
.invoke('text')
.then(value => {
...
})
})
Accessing values by text label like this
const values = {}
cy.get('div.chakra-stack p')
.each($el => {
const frase = $el.text()
cy.wrap($el).prev().invoke('text')
.then(value => values[frase] = +value)
})
.then(() => {
// values = {'shield': 1, 'session': 2, ...}
})
I have a custom command that gets me my elements with the data-cy attribute.
Cypress.Commands.add("getById", (id) => {
cy.get(`[data-cy=${id}]`)
})
everything's working fine.
Now it would be nice if I had the same with find. It would be looking like this:
Cypress.Commands.add("findById", { prevSubject: true }, (subject, id) => {
cy.wrap(subject).find(`[data-cy=${id}]`)
})
The problem there is that cypress throws an error with this code:
cy.root().then((root) => {
if(root.findById("...").length) {
...
}
})
The error is "root.findById" is not a function.
Can you help me write that custom command correctly?
The basic problem is that subject passed in to the command is already wrapped, so just chain the find() from it. Also you need to return the result to use it in the test.
Custom command
Cypress.Commands.add("findById", { prevSubject: true }, (subject, id) => {
return subject.find(`[data-cy=${id}]`)
})
The next problem is you can't mix 'ordinary' js code with Cypress commands, so the returned value must be accessed from a .then().
Spec
describe('...', () => {
it('...', () => {
cy.visit('app/find-by-id.html')
cy.root().findById('2').then(el => {
console.log('found', el, el.length)
expect(el.length).to.eq(2)
})
})
})
Html used to test the test (app/find-by-id.html)
<div>
<div data-cy="1"></div>
<div data-cy="2"></div>
<div data-cy="2"></div>
<div data-cy="3"></div>
</div>
Adding to #Richard Matsen's answer, you might want to add some log into your command, so that it appears well in your cypress log, just as if you had used .find(...) directly:
Cypress.Commands.add(
"findByTestId",
{
prevSubject: ["element"],
},
(
subject: Cypress.Chainable<HTMLElement>,
testId: string,
options?: Partial<
Cypress.Loggable &
Cypress.Timeoutable &
Cypress.Withinable &
Cypress.Shadow
>
) => {
const $el = subject.find(`[data-testid=${testId}]`, options);
Cypress.log({
$el: $el as any,
name: "findByTestId",
message: testId,
});
return $el;
}
);