writing unit tests for vue-multiselect - javascript

I'm trying to work out how to write tests for vue-multiselect and having trouble.
Specifically, I'm trying to "click" the input to open the dropdown (before then selecting an option), however nothing is working
I'ved tried
vm.$el.querySelector('.multiselect').click()
and in the browser:
document.querySelector('.multiselect').click()
and lots of other combinations but nothing's working.
Odd for a library which emphasises it's test coverage not to give an docs (I could find on how) to use it in unit tests.

At last got this working, the key was .dispatchEvent(new window.Event('focus')) not .focus().
Relevant bit of final test:
expect(vm.$el.querySelectorAll('input')).to.have.lengthOf(1)
vm.$el.querySelector('.multiselect').dispatchEvent(new window.Event('focus'))
await tick()
const s = vm.$el.querySelectorAll('.multiselect__element')[2].querySelector('span')
expect(s.innerText).to.equal('Science')
s.dispatchEvent(new window.Event('mousedown'))
await tick()
expect(routes_visited).to.deep.equal(['/s/3-science'])
vm.$el.querySelector('.cross').click()
await tick()
expect(routes_visited).to.deep.equal(['/s/3-science', '/'])
(note my component changes the vue-router route, so I'm watching routes and pushing into routes_visited in the test to track changes.)

Related

"No element found using locator..." when performing e2e testing with cucumber

I get the folowing failure on several features of Cucumber "NoSuchElementError: No element found using locator: By(css selector, h1)"
I have tried to set a bigger timeout in order to give Cucumber more time to find the elements, but it doesn't seem to work
Here are the main components of teh test:
cardTitle.feature:
#cardTitle-feature
Feature: See card title
Display the card title
#cardTitle-scenario
Scenario: Card Page
Given I am on the card page
When I do nothing
Then I should see the card title
app.steps.ts:
// Go to the card - Display the title
Given(/^I am on the card page$/, async () => {
await page.navigateToCard();
});
When(/^I do nothing$/, () => {
});
Then(/^I should see the card title$/, async () => {
expect(await page.getCardTitleText()).to.equal('Profile');
});
app.po.ts:
navigateToCard() {
this.sleep(3000);
return browser.get('/card');
}
getCardTitleText() {
this.sleep(3000);
return element(by.css('h1')).getText();
}
card.html:
<div class="profile-container">
<!-- EXAMPLE TOP NAV -->
<h1>Profile</h1>
...
I think that this could happen because "card" may not be accessible without login in the application. If this is the problem, how could I perform a test that logs into the application and then checks the "h1" element?
Thank you!
Great write up! Thanks for all the detail, that helps a lot. Here are my thoughts:
Don't you need to await the sleeps in your page object? Or promised chain the sleep to the get, if you're avoiding async functions in your page object for some reason.
Given that you're using protractor, and presumably this is an angular app, I'm surprised that you would need sleeps at all. Usually the built in waitForAngular that runs as part of every browser.get should wait until the page is fully loaded, before continuing
Your css looks perfect, that should work just fine. You can locate both html tags and attribute with css.
I'm assuming this.sleep is a method in your page object base class or something? I was kind of expecting browser.sleep.
Btw, I've gotten a lot of mileage out of the $ and $$ aliases in protractor, they're so clean. You could shorten
return element(by.css('h1')).getText();
To just
return $('h1').getText();
If you prefer.

Using Jest's todo feature

The release notes for Jest 24 highlighted a new feature that I want to make use of: test.todo. However, for the life of my I am unable to use it.
For example, I want to sketch out tests in my subscriptions.test.ts file so I create the following:
describe('Subscription Tests', () => {
test.todo('... a name');
});
The TypeScript compiler then promptly presents me with a red line under todo saying, Property 'todo' does not exist on type 'It'.
I am sure I am missing something obvious but I've hit the wall at this point. Can someone help?
Thanks to the comment from #jonrsharpe I ran yarn upgrade #types/jest --latest and that resolved my problem. Urgh -- could not see the wood for the trees!
I feel pretty dumb for a while because my test was failing after adding the todo(). I shoud've read the documentation more thoroughly. Here is my problematic code:
test("should show progress indicator when authorizing", () => {
test.todo("should show progress indicator when authorizing")
})
But it need to be like the below. Passing callback when using todo and nested test() in the callback are not allowed.
test.todo("should show progress indicator when authorizing")

AngularJS 1.7 Module Injection For Tests Error

My AngularJS (1.7.x) application has a custom filter that I want to write tests around it, and I decided to use Jest to perform this task.
My main issue is that as I follow this tutorial by Curt, I am struggling to properly get the filter (which has no outside dependencies so I thought it was the prime target to introduce unit tests with) to load within the test harness.
For starters, here is a simplified version of the filter for the purpose of this question:
angular.module('app.module').filter('takeTheThing', () =>
function (parameter1) {
return `${parameter1} thing!`;
}
);
And, after following the tutorial above, as well as reading up on another SO question specific to testing AngularJS filters, I have attempted every conceivable version of my simple test file as follows but receive a cryptic error message from Angular about it:
require('../node_modules/angular/angular.min.js');
require('../node_modules/angular-mocks/angular-mocks.js');
//Commenting or un-commenting this, results in module-related injector errors:
//require('./takeTheThing.filter.js');
describe('The thingerizer', () => {
let $filter;
beforeEach(angular.mock.module('app.module'));
//Injecting this specifically, or _$filter_ still errors:
beforeEach(inject(takeTheThingFilter => {
$filter = takeTheThingFilter;
}));
//Injecting here instead of in the beforeEach, same issue
it('should give me something', () => {
//Calling the specific filter or thru the Angular $filter... Same
const actual = $filter(1);
expect(actual).toEqual('1 thing!');
});
});
I'm pulling my hair out, but there's something quite basic I'm missing in regards to the test setup (specifically, how to load the app "correctly" without whole-hog loading my entire application). What gives?
AngularJS: 1.7.5
Angular Mocks: 1.7.6
Jest: 23.6.0 (I am using gulp-jest but even when I directly call jest from within the bin folder, I get the exact same errors, so I omitted most of those details here)

How to add text to the Mocha output reports

I want to track some values, like timings and gasused. I can return this using console.log(), collecting it, is not the problem. But would like a more robust and nicer method to report it than console.log().
A simplyfied example:
it("I can reserve up to 10.000", async() => {
let instance = await FullCoupon.new(10000);
// in reality this is a helper function to collect and output the values.
var tx = await web3.eth.getTransactionReceipt(instance.transactionHash);
console.log(tx.gasUsed);
//...
});
The above example would print inline and unpadded number (the 53855 in the screenshot):
What I am looking for, is, preferably to collect messages during the test-run and print them below the test-output. Where my test-suite prints the > No events were emitted for example.
Or, alternatively, to add texts to the test-line being printed, similar to the slow-test-timing flags, the (185ms) for example.
Does Mocha offer an API to set messages to be printed into its reports?
There certainly is a way of doing it. You can use some other reporter which supports this kind of feature. You can try using mochaawesome it has a feature to add details to individual test result.
To add some test to your test report, you can use code as below:
const addContext = require('mochawesome/addContext');
From inside it block:
addContext(<value you want to print>);
To use this reporter use --reporter mochawesome while triggering your test suite.
This will print the text in test report. There are other reporters as well which support this kind of features. Hope this solves the problem.

Mocha tests on focus-related behaviors (Backbone/CoffeeScript app)

I have a Backbone app written in CoffeeScript. I'm trying to use Mocha (with Chai and Sinon) to write tests for DOM-related behaviors, but it seems that hidden fixtures (I'm using js-fixtures now but I've also tried this unsuccessfully with a hidden '#fixtures' div) don't register certain DOM-related behaviors which makes testing certain types of DOM-related behaviors (seemingly) impossible.
For example, my main app view has several subviews which are never rendered at the same time: when the app view renders subview A, it remembers the focused element of the currently active subview B (#_visibleView), saves that information on subview B, closes the subview B, and then renders subview A.
_rememberFocusedElement: ->
focusedElement = $ document.activeElement
if focusedElement
focusedElementId = focusedElement.attr 'id'
if focusedElementId
#_visibleView?.focusedElementId = focusedElementId
This works when I test it manually, but when I try to write unit tests for this behavior they fail because I can't set focus (e.g., via $(selector).focus()) to an element in a hidden div/iframe. (I have the same issue with functionality which listens for window resize events.)
I thought that if I changed $ document.activeElement to #$ ':focus" I might get different results, but that doesn't fix the issue.
Here is what the relevant parts of my Mocha (BDD) tests look like. This spec will print TEXTAREA to the console and then undefined, indicating that there is a textarea with id='transcription' but I can't set focus to it.
beforeEach (done) ->
fixtures.path = 'fixtures'
callback = =>
#$fixture = fixtures.window().$ "<div id='js-fixtures-fixture'></div>"
#appView = new AppView el: #$fixture
done()
describe 'GUI stuff', ->
it 'remembers the currently focused element of a subview', (done) ->
#appView.mainMenuView.once 'request:formAdd', =>
#appView._visibleView.$('#transcription').focus()
console.log #appView._visibleView.$('#transcription').prop 'tagName'
console.log #appView._visibleView.$(':focus').prop 'tagName'
done()
#appView.mainMenuView.trigger 'request:formAdd'
Is there any way that I can write unit tests for these types of behaviors?
Ok, first off let me clarify something: the term "unit test" means man different things to many people. Often times it becomes synonymous with "any test written using a unit test framework (like Mocha)". When I use the term "unit test" that's not what I mean: what I mean is a test that tests only a single unit of work (which, in a JS environment, will usually be a single function, but might be a whole class).
Ok, with that out of the way, if you really are trying to unit test your code, you're sort of taking the wrong approach. A unit test really shouldn't rely on anything outside the context of the function being tested, and so relying on the (external) DOM is where your problem lies.
Let's assume your focus-handling code is in a function called handleFocus (I don't know the actual method name). Consider the following test, which I'll write using JavaScript since my CoffeScript is rusty:
describe('#handleFocus', function() {
it('remembers the currently focused element of a subview', function() {
var setFocusStub = sinon.stub($.fn, 'focus');
appView._visibleView.handleFocus();
expect(setFocusStub.calledOnce).to.be(true);
});
});
The above is a bit of an over-simplification, but hopefully it illustrates the point. What you're really trying to check isn't whether the DOM (fake or real) does X; what you're trying check is whether your function does X. By focusing on that in your test, and relying on a stub that checks whether "X" happened or not, you completely eliminate the need for the DOM to be involved.
Now of course you might wonder: "well great, that helps me in test-land, but how do I know it will work in a real environment?" My answer to that would be that your (probably Selenium-based) acceptance tests should cover that sort of thing. Acceptance tests should check whether your overall code works in the real world, while unit tests should ensure that individual pieces of that code work in a fake environment.
The former is great for ensuring your customers don't see bugs, while the latter is great for figuring out exactly where those bugs come from, and for making it possible for you to refactor safely.

Categories

Resources