Skip to content

25th April 2022

Coding

  • New: Add Cypress commands.

    For the functions you write a lot you can use commands in /cypress/support/commands.ts.

    Cypress.Commands.add('getById', (selector, ...args) => {
      return cy.get(`[data-cy=${selector}]`, ...args)
    })
    
    Cypress.Commands.add('getByIdLike', (selector, ...args) => {
      return cy.get(`[data-cy*=${selector}]`, ...args)
    })
    
    Cypress.Commands.add('findById', {prevSubject: true}, (subject, selector, ...args) => {
      return subject.find(`[data-cy=${selector}]`, ...args)
    })
    

    So you can now do

    cy.getById('submit')
    

  • New: Add more ways to select elements.

    • Select by position in list

    Inside our list, we can select elements based on their position in the list, using .first(), .last() or .eq() selector.

    cy
      .get('li')
      .first(); // select "red"
    
    cy
      .get('li')
      .last(); // select "violet"
    
    cy
      .get('li')
      .eq(2); // select "yellow"
    

    You can also use .next() and .prev() to navigate through the elements.

    • Select elements by filtering

    Once you select multiple elements, you can filter within these based on another selector.

    cy
      .get('li')
      .filter('.primary') // select all elements with the class .primary
    

    To do the exact opposite, you can use .not() command.

    cy
      .get('li')
      .not('.primary') // select all elements without the class .primary
    
  • New: Finding elements.

    You can specify your selector by first selecting an element you want to search within, and then look down the DOM structure to find a specific element you are looking for.

    cy
      .get('.list')
      .find('.violet') // finds an element with class .violet inside .list element
    

    Instead of looking down the DOM structure and finding an element within another element, we can look up. In this example, we first select our list item, and then try to find an element with a .list class.

    cy
      .get('.violet')
      .parent('.list') // finds an element with class .list that is above our .violet element
    
  • New: Assert on the content of an attribute.

    cy
      .get('a')
      .invoke('attr', 'href')
      .should('eq', 'https://docs.cypress.io')
    
  • New: Use the content of a fixture set in a hook in a test.

    If you store and access the fixture data using this test context object, make sure to use function () { ... } callbacks both for the hook and the test. Otherwise the test engine will NOT have this pointing at the test context.

    describe('User page', () => {
      beforeEach(function () {
        // "this" points at the test context object
        cy.fixture('user').then((user) => {
          // "this" is still the test context object
          this.user = user
        })
      })
    
      // the test callback is in "function () { ... }" form
     it('has user', function () {
        // this.user exists
        expect(this.user.firstName).to.equal('Jane')
      })
    })
    
  • New: Run only failing tests.

    Cypress doesn't Allow to rerun failed tests but you can use it.only on the test you want to run.

  • New: Make HTTP requests with Vue.

    Compare Fetch API and Axios when doing http requests to external services.

    Explain how to do them with both methods and arrive to the conclusion that if you’re working on multiple requests, you’ll find that Fetch requires you to write more code than Axios, even when taking into consideration the setup needed for it. Therefore, for simple requests, Fetch API and Axios are quite the same. However, for more complex requests, Axios is better as it allows you to configure multiple requests in one place.

    If you're making a simple request use the Fetch API, for the other cases use axios because:

    Axios provides an easy-to-use API in a compact package for most of your HTTP communication needs. However, if you prefer to stick with native APIs, nothing stops you from implementing Axios features.

    For more information read:

  • New: Simulate errors.

    context('Errors', () => {
      const errorMsg = 'Oops! Try again later'
    
      it('simulates a server error', () => {
        cy.intercept(
          'GET',
          '**/search?query=cypress',
          { statusCode: 500 }
        ).as('getServerFailure')
    
        cy.visit('https://example.com/search')
    
        cy.get('[data-cy="search-field"]')
          .should('be.visible')
          .type('cypress{enter}')
        cy.wait('@getServerFailure')
    
        cy.contains(errorMsg)
          .should('be.visible')
      })
    
      it('simulates a network failure', () => {
        cy.intercept(
          'GET',
          '**/search?query=cypressio',
          { forceNetworkError: true }
        ).as('getNetworkFailure')
    
        cy.visit('https://example.com/search')
    
        cy.get('[data-cy="search-field"]')
          .should('be.visible')
          .type('cypressio{enter}')
        cy.wait('@getNetworkFailure')
    
        cy.contais(errorMsg)
          .should('be.visible')
      })
    })
    
  • New: Handling errors doing requests to other endpoints.

    To catch errors when doing requests you could use:

    try {
        let res = await axios.get('/my-api-route');
    
        // Work with the response...
    } catch (error) {
        if (error.response) {
            // The client was given an error response (5xx, 4xx)
            console.log(err.response.data);
            console.log(err.response.status);
            console.log(err.response.headers);
        } else if (error.request) {
            // The client never received a response, and the request was never left
            console.log(err.request);
        } else {
            // Anything else
            console.log('Error', err.message);
        }
    }
    

    The differences in the error object, indicate where the request encountered the issue.

    • error.response: If your error object has a response property, it means that your server returned a 4xx/5xx error. This will assist you choose what sort of message to return to users.

    • error.request: This error is caused by a network error, a hanging backend that does not respond instantly to each request, unauthorized or cross-domain requests, and lastly if the backend API returns an error.

      This occurs when the browser was able to initiate a request but did not receive a valid answer for any reason.

    • Other errors: It's possible that the error object does not have either a response or request object attached to it. In this case it is implied that there was an issue in setting up the request, which eventually triggered an error.

      For example, this could be the case if you omit the URL parameter from the .get() call, and thus no request was ever made.

  • New: Use Flexbox with Vuetify.

    Control the layout of flex containers with alignment, justification and more with responsive flexbox utilities.

    Note

    "I suggest you use this page only as a reference, if it's the first time
    you see this content, it's better to see it at the
    [source](https://vuetifyjs.com/en/styles/flex) as you can see Flex in
    action at the same time you read, which makes it much more easy to
    understand."
    

    Explain how to use:

  • New: Illustrations.

    You can get nice illustrations for your web on Drawkit, for example I like to use the Classic kit.

Python

Python Snippets

  • New: Get the attribute of an attribute when sorting.

    To sort the list in place:

    ut.sort(key=lambda x: x.count, reverse=True)
    

    To return a new list, use the sorted() built-in function:

    newlist = sorted(ut, key=lambda x: x.body.id_, reverse=True)
    

Other

  • New: Troubleshoot Failed to resolve component: X.

    If you've already imported the component with import X from './X.vue you may have forgotten to add the component to the components property of the module:

    export default {
      name: 'Inbox',
      components: {
        X
      }
    }