I'm doing some testing and I intercept some api calls to the same url, I do one beforeEach, and then another one on the test, but for some reason I does not understand that I changed the alias. I was doing some reading, and the overriding was fixed, but apparently is not?
Please feel free to ask more questions.
Hope I can get some input.
My code:
// Describe block:
beforeEach(() => {
cy.visit("/");
cy.intercept(
{
method: "GET",
url: "/customers*",
hostname: "local.api",
},
{
fixture: "customers.json",
}
).as("customers");
cy.get("[class^=ant-menu-item]", { multiple: true }).eq(1).click();
cy.wait("#customers");
});
[
["customerName", "ASC", 0],
["nextReviewDate", "ASC", 1],
["nextReviewType", "ASC", 2],
].forEach(([sortValue, sortOrder, index]) => {
it(`Sort by direction ${sortOrder} order ${sortValue}`, () => {
cy.get(".ant-table-column-sorters", { multiple: true }).eq(index).click();
cy.intercept("GET", "/customers*").as("request");
cy.wait("#request").then((interception) => {
cy.wrap(interception.response.statusCode).should("eq", 200);
cy.wrap(interception.request.url).should(
"include",
`https://allica.local.api/customers?page=1&sortBy=${sortValue}&pageSize=5&direction=${sortOrder}`
);
});
});
});
The following error:
If there is not overriding, how can overcome this test?
Thanks in advance.
The intercept is an event listener. It must be set up before the event is triggered
cy.intercept("GET", "/customers*").as("request");
cy.get(".ant-table-column-sorters", { multiple: true }).eq(index).click();
cy.wait("#request").then((interception) => {
...
Actually, there's no change to the intercept between tests so you can just set it once and wait multiple times
before(() => cy.intercept("GET", "/customers*").as("request"))
[
["customerName", "ASC", 0],
["nextReviewDate", "ASC", 1],
["nextReviewType", "ASC", 2],
].forEach(([sortValue, sortOrder, index]) => {
it(`Sort by direction ${sortOrder} order ${sortValue}`, () => {
cy.get(".ant-table-column-sorters").eq(index).click();
cy.wait("#request").then((interception) => {
Related
Since I've been experimenting with Nuxt3 and animation libraries, I came across an issue for which I need help finding a solution for.
I want to do an easy transition with some Javascript hooks no CSS/basic transitions.
When a page loads (onEnter), I want to reduce the height of a fixed black rectangle but for example sake, I'm just going to use the Nuxt example:
<script setup lang="ts">
definePageMeta({
pageTransition: {
name: 'custom-flip',
mode: 'out-in',
onBeforeEnter: (el) => {
console.log('Before enter...')
},
onEnter: (el, done) => {},
onAfterEnter: (el) => {}
}
})
</script>
Everything working fine till you want to add an onBeforeLeave, onLeave or onAfterLeave hook.:
<script setup lang="ts">
definePageMeta({
pageTransition: {
name: 'custom-flip',
mode: 'out-in',
onBeforeEnter: (el) => {
console.log('Before enter...')
},
onEnter: (el, done) => {},
onAfterEnter: (el) => {},
//nothings is logging underneath this
onBeforeLeave: (el) => {},
onLeave: (el, done) => {
console.log('this is not logging to the console...')
},
onAfterLeave: (el) => {}
}
})
</script>
Someone who experienced the same issue?
I have multiple links to test having the same test cases. I wanted to use fixture but it did not work. Can someone please help? I want to reiterate my tests for all links in the json file.
spec.js:
cy.readFile('cypress/fixtures/trial.json').then((details) => {
details.forEach((totest)=>{
cy.visit(totest.url)
})
})
fixture (.json):
"totest":[
{
"url": "https:www.link1.com"
},
{
"url": "https:www.link2.com"}
,
{
"url": "https:www.link3.com"
}
]
Your array is inside the totest property, so you need to add that
cy.fixture('trial.json').then((details) => {
details.totest.forEach((totest) => {
cy.visit(totest.url)
})
})
One test per URL
import details from './cypress/fixtures/trial.json'
//OR
const details = require('./cypress/fixtures/trial.json')
describe('tests URLs', () => {
details.totest.forEach(totest => {
it(`testing ${totest.url}`, () => {
cy.visit(totest.url)
})
})
})
I wanted to check my navigations if it is dead / goes to the expected page,
i have a menu array, now i want to check if the link is not "#" then visit the url and should contain the those links,
so far i am stuck in this stage:
const menus = Menu;
context("Nav items test", () => {
beforeEach(() => {
cy.visit("/");
});
it("should redirect to the expected pages", () => {
cy.get(".navbar-nav>li>a[href!='/#']").each((links, index) => {
cy.wrap(links).click();
cy.url().should("contain", links[0].href);
});
});
export const Menu = [
{
id: 1,
title: "Home",
link: "/",
children: [],
},
{
id: 2,
title: "Consultants",
link: "#",
children: [
{ childTitle: "Find a Doctor", childTo: "/consultant/doctors" },
],
},
{
id: 3,
title: "Services",
link: "/services",
children: [
{
childTitle: "Clinical Laboratory",
childTo: "/services/laboratoryservices",
},
],
},
{
id: 4,
title: "Packages",
link: "/packages",
children: [],
},
];
cy.each() can pass three arguments into the callback - value (the currently yielded value), index (the position of the current value in the overall array), and collection (the entire array of yielded variables).
That being said, your current implementation wouldn't work either, as the DOM where you are getting your initial collection will become unattached when navigating to a new page. I would instead recommend doing two separate tests - one that validates that the href values are what you expect, and another that using cy.visit() to go to those href values does not redirect you.
it('validates the menu item href values are correct', () => {
cy.get(".navbar-nav>li>a[href!='/#']").each(($link, index) => {
cy.wrap($link).should('have.attr', 'href', menus[index].link);
});
});
it('validates navigating to each menu item does not redirect', () => {
menus.forEach((item) => {
cy.visit(item.link)
cy.url().should('eq', `${Cypress.config('baseUrl')}${item.link}`);
});
});
You may have to do some re-working, in case your app adds/removes trailing slashes, or other URL modifications.
Use cy.request() to test links with .each()
const results = []
cy.get(".navbar-nav>li>a[href!='/#']").each($a => {
const link = $a.prop('href')
cy.request({
url: link,
failOnStatusCode: false // allow good and bad responses
})
.then(response => {
results.push({link, ok: response.isOkStatusCode})
})
})
cy.then(() => {
console.log(results)
})
For example,
const results = []
cy.wrap(['http://example.com', 'http://not-valid.com']).each(link => {
cy.request({url: link, failOnStatusCode: false})
.then(result => {
results.push({link, ok: result.isOkStatusCode})
})
})
cy.then(() => {
console.log(results)
})
gives these results:
[
{link: 'http://example.com', ok: true}
{link: 'http://not-valid.com', ok: false}
]
Below is snippet of table-ajax.js file from DataTable module.
My question is what will be Ajax url instead of table_ajax.php if I use IndexAction{} in my Controller. I want to display data from database.
var handleRecords = function () {
var grid = new Datatable();
grid.init({
src: $("#datatable_ajax"),
onSuccess: function (grid) {
},
onError: function (grid) {
},
onDataLoad: function(grid) {
},
loadingMessage: 'Loading...',
dataTable: {
"bStateSave": true, // save datatable state(pagination, sort, etc) in cookie.
"lengthMenu": [
[10, 20, 50, 100, 150, -1],
[10, 20, 50, 100, 150, "All"] // change per page values here
],
"pageLength": 10, // default record count per page
"ajax": {
"url": "table_ajax.php", // ajax source
},
"order": [
[1, "asc"]
]// set first column as a default sort by asc
}
});
Firstly you'll need to add a strategy to your viewmanager so you can return json. This is done within your module.config like so:
'view_manager' => array(
...
'strategies' => array(
'ViewJsonStrategy'
),
...
),
I'll just assume you have this DataTableModule imported via your Autoloader. So you can extend or implement the "table_ajax.php" within your controller and override/add a return value as a zf2 JsonModel.
In your Action within your Controller that extends/implements ajax_table.php
...
return new JsonModel($whateverTheResultIs);
...
Now that you have a controller that returns your JSON you'll require to set up a route. This is pretty straight forward it only links to your controller action and since you defined a strategy in your Viewmanager ZF2 does the rest of the pesky ajax stuff for you.
Edit: Rather then extending the table_ajax.php in your controller it probably is a good idea to write a Service which retrieves the information from table_ajax.php.
Developing a Sencha Touch MVC app that pulls data from json store (thats set up to a DB pulling out content from a Wordpress Blog).
Everything works up until my "detail" panel. Instead of it listening to the TPL, its just dumping some data. The data looks similar to my blog post, but is filled with other code and doesn't make much sense.
Here is a lean version of my list:
myApp.views.PostListView = Ext.extend(Ext.Panel, {
postStore: Ext.emptyFn,
postList: Ext.emptyFn,
id:'postlistview',
layout: 'card',
initComponent: function () {
/* this.newButton = new Ext.Button({
text: 'New',
ui: 'action',
handler: this.onNewNote,
scope: this
});*/
this.topToolbar = new Ext.Toolbar({
title: 'All Posts',
/* items: [
{ xtype: 'spacer' },
this.newButton
],*/
});
this.dockedItems = [ this.topToolbar ];
this.postList = new Ext.List({
store: myApp.stores.postStore,
grouped: true,
emptyText: '<div style="margin:5px;">No notes cached.</div>',
onItemDisclosure: true,
itemTpl: '<div class="list-item-title">{title}</div>' +
'<div class="list-item-narrative"><small>{body}</small></div>',
});
this.postList.on('disclose', function (record) {
this.onViewPost(record);
}, this),
this.items = [this.postList];
myApp.views.PostListView.superclass.initComponent.call(this);
},
onViewPost: function (record) {
Ext.dispatch({
controller: myApp.controllers.masterController,
action: 'viewpost',
post: record
});
},
});
And here is the "detail" view that is called on disclosure:
myApp.views.PostSingleView = Ext.extend(Ext.Panel, {
title:'Single Post',
id:'postsingleview',
layout:'card',
style:'background:grey;',
initComponent: function () {
this.new1Button = new Ext.Button({
text: 'Back',
ui: 'back',
handler: this.onViewList,
scope: this,
dock:"left"
});
this.top1Toolbar = new Ext.Toolbar({
items: [
this.new1Button
],
title: 'Single Posts',
});
this.postSinglePanel = new Ext.Panel({
layout:'fit',
flex:1,
scroll: 'vertical',
style:'padding:10px;background:yellow;',
itemTpl: '<tpl for=".">' +
'<div class="list-item-narrative">{body}</div>' +
'</tpl>',
});
this.dockedItems = [ this.top1Toolbar, this.postSinglePanel ];
myApp.views.PostSingleView.superclass.initComponent.call(this);
},
onViewList: function () {
Ext.dispatch({
controller: myApp.controllers.masterController,
action: 'viewlist',
});
},
});
And here is the controller that its talking to:
Ext.regController('masterController', {
'index': function (options) {
if (!myApp.views.mainView) {
myApp.views.mainView = new myApp.views.MainView();
}
myApp.views.mainView.setActiveItem(
myApp.views.postView
);
},
'viewpost': function (options) {
myApp.views.postSingleView.postSinglePanel.update(options.post);
myApp.views.postView.setActiveItem(
myApp.views.postSingleView,
{ type: 'slide', direction: 'left' }
);
},
});
myApp.controllers.masterController = Ext.ControllerManager.get('masterController');
When the data comes out, it looks similar to this:
http://i.imgur.com/QlQG8.png
(the black boxes are "redacted" content, no error code there).
In closing, I believe that the controller is "dumping" the data into "MyApp.views.PostSingleView" rather than formatting it as I request in the TPL, though I'm not sure how to fix it. Any and all help MUCH appreciated!
UPDATE: As requested, here is the RegModel:
Ext.regModel("CategoryModel", {
fields: [
{name: "id", type: "int"},
{name: "title", type: "string"},
{name: "body", type: "string"},
],
hasMany: {
model: 'Post',
name: 'posts'
}
});
And here is a sample of the json:
{
"status":"ok",
"post":{
"id":1037,
"type":"post",
"slug":"post-title",
"url":"http:\/\/localhost:8888\/jsontest\/PostTitle\/",
"status":"publish",
"title":"Post Title",
"title_plain":"Post Title",
"content":"<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.<br \/>\nLorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.<\/p>\n<!-- PHP 5.x -->",
"excerpt":"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat [...]",
"date":"2011-07-29 14:17:31",
"modified":"2011-08-30 01:33:20",
"categories":[
{
"id":87,
"slug":"the-category",
"title":"The Category",
"description":"",
"parent":17,
"post_count":5
}
],
"tags":[
],
"author":{
"id":2,
"slug":"tom",
"name":"tom",
"first_name":"tom",
"last_name":"",
"nickname":"",
"url":"",
"description":""
},
"comments":[
],
"attachments":[
],
"comment_count":0,
"comment_status":"open"
},
"previous_url":"http:\/\/localhost:8888\/jsontest\/next-post\/",
"next_url":"http:\/\/localhost:8888\/jsontest\/prev-post\/"
}
Use the tpl config option of the Ext.Panel not the itemTpl which doesn't exist.
As someone has mentioned before, be careful when using a Model instance and the update method, you will need to use the model's data property.
Try using this:
myApp.views.postSingleView.postSinglePanel.update(options.post.data);
the reason is that post does not actually expose the underlying data directly, you need to use the property data for that.
Also any particular reason why you are docking the postSinglePanel? I would be very careful using too many docked items as they are a known source of bugs and layout issues.
A simple way is to write your own method to update child panels (you can also see to override the default update method)
myApp.views.PostSingleView = Ext.extend(Ext.Panel, {
initComponent: function () {
// [...]
},
// [...]
myUpdate: function(data) {
this.postSinglePanel.update(data);
this.doComponentLayout(); // not sure if necessary...
}
});
and from your controller:
Ext.regController('masterController', {
// [...]
'viewpost': function (options) {
myApp.views.postSingleView.myUpdate(options.post.data); // note the .data
// [...]
},
});