Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[EOSF-594] Add example controller unit tests and component integration tests #293

Merged
merged 33 commits into from
Apr 28, 2017

Conversation

hmoco
Copy link
Contributor

@hmoco hmoco commented Mar 3, 2017

This PR has been diminished in scope due to problems found with acceptance testing. Ticket previously tracking this PR is https://openscience.atlassian.net/browse/EOSF-510

Ticket

https://openscience.atlassian.net/browse/EOSF-594

Purpose

Improve test coverage, with integration and controller tests, to allow simpler future tests writing.

Changes

Use of ember-osf factories

@hmoco hmoco changed the title [WIP] Feature/tests [EOSF-510] Add example acceptance tests, controller unit tests, and component integration tests Mar 10, 2017
@binoculars
Copy link
Member

@hmoco tests are failing, can you fix?

bower.json Outdated
@@ -12,7 +12,8 @@
"toastr": "^2.1.2",
"hint.css": "^2.3.2",
"jquery.tagsinput": "^1.3.6",
"loaders.css": "^0.1.2"
"loaders.css": "^0.1.2",
"jquery-mockjax": "~2.2.1"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jquery-mockjax sounds like something used only for testing. Could I suggest moving it to devDependencies instead of dependencies?

See: http://stackoverflow.com/questions/19339227/bower-and-devdependencies-vs-dependencies

Copy link
Contributor

@abought abought left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's really good to see a start on testing. I can see some of the scaffolding here being very useful going forward.

That said, I do have a few suggestions on tests, eg making sure the acceptance tests focus on user facing behavior, and also possible ways to make the unit tests more concise / independent. Hopefully these will act as examples for future work.

In a few cases, it seems that your tests may have caught minor cosmetic bugs? Helping already!

package.json Outdated
"ember-font-awesome": "2.1.1",
"ember-get-config": "0.0.4",
"ember-i18n": "4.3.1",
"ember-link-action": "0.0.35",
"ember-load-initializers": "^0.5.1",
"ember-metrics": "0.6.3",
"ember-osf": "0.3.0",
"ember-osf": "https:/CenterForOpenScience/ember-osf.git#014fa91a442d4f2b8afe2adf0463acc1e3723ad3",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦑 Note: this is fine for local testing, but should be changed to a real ember-osf release before this gets merged. (blocking change)


moduleForAcceptance('Acceptance | content');

test('visiting /content', function(assert) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test does not appear to do anything.

Rather than comment out broken functional code, consider using skip() in place of test(). This will help us track problematic tests for followup. We try to avoid committing comment blocks when possible.


moduleForAcceptance('Acceptance | discover');

test('visiting /discover', function(assert) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the one hand it's nice we test these things. On the other hand, I'm fairly sure there's a way for no-value query params to simply be omitted from the URL.

Is ?provider=&subject= a design behavior we want to test for, or a cosmetic bug?

visit('preprints/discover?provider=OSF&subject=Business');

andThen(() => {
let controller = container.lookup('controller:discover');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A good quote from the docs:

Acceptance tests are used to test user interaction and application flow. The tests interact with the application in the same ways that a user would, by doing things like filling out form fields and clicking buttons...

In general, it seems like the acceptance test should focus on what the result looks like to the user, without knowing how the internals (the controller) are implemented. Perhaps the things that check controller behavior would be better suited to, say, a unit test?

To make the difference actionable for this PR- one thing we could do is to check whether the desired checkboxes are correctly selected. That's a user-facing behavior related to the query params, and a good candidate for an acceptance test.

}
this.application = startApp();
FakeServer.start();
manualSetup(this.application.__container__);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

General comment for this PR: is this necessary?

From docs:

By default, you only need to call manualSetup(this.container) in unit/component tests

See also the factory guy setup for comparison in case it sparks some ideas:
https:/danielspaniel/ember-data-factory-guy/blob/master/tests/helpers/module-for-acceptance.js

year: '{{year}}',
copyright_holders: ['{{copyrightHolders}}']
});
ctrl.notifyPropertyChange('model.license');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See questions above about computeds/ use of notifyPropertyChange.

Also, if we are intending to test multiple different scenarios, I generally recommend doing each in a separate test to ensure that the behaviors are isolated. It does not appear that the three scenarios are interdependent, though I could be missing something.

let ctrl = this.subject();
let node = FactoryGuy.make('node');
ctrl.set('node', node);
Ember.run(() => {
Copy link
Contributor

@abought abought Mar 23, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. In general, whenever you put code in a run loop, you want to make sure it actually ran before the test ended. One very easy safeguard is to use assert.expect(99) at the very top of the test (outside the run loop) to tell it how many assertions you thought would run. (this has saved me a few times when testing async behavior)

  2. Does this need to be in Ember.run? If not, item 1 might not be necessary. ;)

  3. Realistically, there are three separate scenarios that could each be a separate test(). If we shorten this to provide each description when the node is first created, I think we can do away with the .run and the notifyPropertyChange altogether.

Eg: let user = make('node', {description: 's'.repeat(350)});

let description = 'string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string str';
let notExpanded = description.slice(0, 350);
node.set('description', description);
ctrl.notifyPropertyChange('description');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned elsewhere, not sure this part is needed?

Also, each scenario should be its own test to ensure isolation.

//Test less than 350 doesn't use description (uses node.description)

ctrl.set('expandedAbstract', true);
// expandedAbstract logic has been moved to the template, making the expanded tests unnescessary here.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per this note: does this mean that any code after the last assertion can be removed?

manualSetup(this.application.__container__);
const url = config.OSF.apiUrl;
const provider = FactoryGuy.build('preprint-provider');
stubRequest('get', url + '/v2/users/me', (request) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks helpful!

I ran the tests in chrome with the network inspector open, and noticed that the page still sends a request to google analytics every time tests run. This may indicate one more thing that needs stubbing. Thoughts?

@hmoco hmoco changed the title [EOSF-510] Add example acceptance tests, controller unit tests, and component integration tests [EOSF-594] Add example controller unit tests and component integration tests Mar 31, 2017
Copy link
Member

@jamescdavis jamescdavis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a great start on improving test coverage. My only reservations are to make sure that even minor formatting changes are mentioned in Side Effects and that I recommend adding messages when there is more than one assertion in a test to make it clear why a test is failing. In general, I think messages are useful, even when there is only one assertion, and even if the assertion is somewhat obvious. I always think it's better to give explicit feedback when it comes to test failures.

@@ -137,7 +137,7 @@ export default Ember.Controller.extend(Analytics, {
let text = this.get('model.license.text');
if (text) {
text = text.replace(/({{year}})/g, this.get('model.licenseRecord').year || '');
text = text.replace(/({{copyrightHolders}})/g, this.get('model.licenseRecord').copyright_holders ? this.get('model.licenseRecord').copyright_holders.join(',') : false || '');
text = text.replace(/({{copyrightHolders}})/g, this.get('model.licenseRecord').copyright_holders ? this.get('model.licenseRecord').copyright_holders.join(', ') : false || '');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though this change is minor, it'd be good to mention it in Side Effects just to bring it to attention of QA and others.

contributor = Ember.merge(contributor, contributorModel.serialize().data.attributes);
this.set('contributor', contributor);
this.render(hbs`{{author-link contributor=contributor}}`);
assert.ok(!this.$('a').length);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add message?

this.set('contributor', contributor);
this.render(hbs`{{author-link contributor=contributor}}`);
assert.ok(!this.$('a').length);
assert.equal(this.$().text().trim(), contributorModel.get('users.fullName'));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add message?

this.set('contributor', contributor);

this.render(hbs`{{author-link contributor=contributor}}`);
assert.ok(this.$('a').length);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add message?


this.render(hbs`{{author-link contributor=contributor}}`);
assert.ok(this.$('a').length);
assert.equal(this.$().text().trim(), contributorModel.get('users.fullName'));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add message?

assert.ok(ctrl.get('useShortenedDescription'));

node.set('description', 'string'.repeat(100).slice(0, 350));
assert.ok(!ctrl.get('useShortenedDescription'));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add message?

assert.ok(!ctrl.get('useShortenedDescription'));

node.set('description', 'string'.repeat(100).slice(0, 349));
assert.ok(!ctrl.get('useShortenedDescription'));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add message?

let description = 'string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string string str';
let notExpanded = description.slice(0, 350);
node.set('description', description);
assert.equal(ctrl.get('description'), notExpanded.trim());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add message?

description = 'string stringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstringstring';
notExpanded = 'string ';
node.set('description', description);
assert.equal(ctrl.get('description'), notExpanded.trim());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add message?

@@ -304,7 +304,7 @@ export default Ember.Controller.extend(Analytics, BasicsValidations, NodeActions
let license = this.get('model.license');
return {
year: record ? record.year : null,
copyrightHolders: record && record.copyright_holders ? record.copyright_holders.join(',') : null,
copyrightHolders: record && record.copyright_holders ? record.copyright_holders.join(', ') : null,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SAA about mentioning this in Side Effects.

@binoculars
Copy link
Member

Probably should revert changes in controllers, as I've made major updates in #319

@jamescdavis
Copy link
Member

Indeed. It looks like #319 should probably be merged first? There will likely be several merge conflicts.

Copy link
Member

@jamescdavis jamescdavis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to add a submit controller test for multiple copyright holders.

@@ -684,7 +684,7 @@ export default Ember.Controller.extend(Analytics, BasicsValidations, NodeActions
this.set('basicsLicense', {
licenseType: license || this.get('availableLicenses').toArray()[0],
year: this.get('model.licenseRecord') ? this.get('model.licenseRecord').year : date.getUTCFullYear().toString(),
copyrightHolders: this.get('model.licenseRecord') ? this.get('model.licenseRecord').copyright_holders.join(',') : ''
copyrightHolders: this.get('model.licenseRecord') ? this.get('model.licenseRecord').copyright_holders.join(', ') : ''
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to add a test for this.

Copy link
Member

@jamescdavis jamescdavis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recommend using the wait() test helper instead to test asynchronous parts of the discardBasics action.

…) test helper instead

Upgrading to ember-cli-qunit 3 was required due to bug in v2 that prevents use of asynchronous wait helpers.
@hmoco
Copy link
Contributor Author

hmoco commented Apr 28, 2017

@brianjgeiger, can't get this to fail locally, can't get it to pass here. Any ideas?

@jamescdavis
Copy link
Member

merge develop, then it will fail locally

@jamescdavis
Copy link
Member

Also, I wanted to reference ember-cli/ember-cli-qunit#162, which discusses the issue using wait helpers with qunitjs < 2.3.1 and qunitjs/qunit#1148, which was the fix to qunitjs that allows assertions after assert.async(). Switching to ember-cli-qunit 3 was necessary because ember-cli-qunit 2 depends on qunitjs 1.

Copy link
Member

@jamescdavis jamescdavis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Contributor

@brianjgeiger brianjgeiger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved by @jamescdavis

@brianjgeiger brianjgeiger merged commit 65b3d66 into develop Apr 28, 2017
@jamescdavis jamescdavis deleted the feature/tests branch November 14, 2018 18:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants