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

Upgrade to inspectpack@4. Add regression tests to catch imports of format* utils. #263

Merged
merged 1 commit into from
Nov 25, 2018

Conversation

parkerziegler
Copy link
Contributor

@ryan-roemer @ElreyB @ianwsperber Here's a WiP PR for the [email protected] migration! Don't merge yet, I'm still underway adding tests but wanted to get some 👀on things so far.

I haven't undertaken any UI updates to leverage new inspectpack in this PR, mostly because I want to ensure we can get webpack-dashboard fully operational with latest inspectpack. The focus of this PR is on testing and code coverage, and adding regression tests for our format* utils.

I'm going to drop comments in the diff below around some things I've uncovered while testing. Would appreciate any initial feedback you have!

};

expect(dashboard.setProgress(data)).to.not.throw;
expect(dashboard.progressbar.setProgress).to.have.been.calledOnce;
Copy link
Contributor Author

@parkerziegler parkerziegler Nov 11, 2018

Choose a reason for hiding this comment

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

I wanted to make these asserts more firm, i.e. to.have.been.calledWith, but I'm hitting the good ol' JS-floating-point-math-is-horrible thing. The crux of the issue is that a float like 0.57 gets evaluated in our calculations in this method as 0.56999999997 (or something of the like), and our rounding setup returns 0.56 / 56%. Not sure if we want to update our rounding logic in this method, but wanted to call out that this is happening. I don't like the idea of writing:

const data = {
   value: 0.57
};

expect(dashboard.progressbar.setProgress).to.have.been.calledWith(0.56);

expect(dashboard.screen.render).to.have.been.called;
});

it("can setProblems", () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

So I'm having a hard time getting formatProblems import properly tested. The issue is that setProblems, which is the only method that uses formatProblems, doesn't actually invoke formatProblems. Rather, formatProblems is called in a function that gets assigned to a particular key in our problemsItems collection. So the function is created but never actually run in our current tests, so that import, as far as I can tell, never gets tested. If I change the import syntax on that util, all tests still pass 😬 So, not much of a regression test 😞 Let me know if any of you have a thought on a way to solve this.

Copy link
Member

Choose a reason for hiding this comment

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

I'm looking at this and will try to get to a bit more by sometime on Tuesday...

Copy link
Member

@ryan-roemer ryan-roemer Nov 12, 2018

Choose a reason for hiding this comment

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

I think something like this may get you where you want to be:

diff --git a/test/dashboard/index.spec.js b/test/dashboard/index.spec.js
index 6c9dd5b..4cf3a98 100644
--- a/test/dashboard/index.spec.js
+++ b/test/dashboard/index.spec.js
@@ -1,8 +1,9 @@
 "use strict";
 
 const chalk = require("chalk");
-require("../base.spec");
+const base = require("../base.spec");
 
+const blessed = require("blessed");
 const Dashboard = require("../../dashboard");
 
 describe("dashboard", () => {
@@ -122,6 +123,21 @@ describe("dashboard", () => {
     });
 
     it("can setProblems", () => {
+      // Override ListBar fakes from what we do in `base.spec.js`.
+      // Note that these are **already** stubbed. We're not monkey-patching blessed.
+      blessed.listbar.returns({
+        selected: "selected",
+        setLabel: base.sandbox.spy(),
+        setProblems: base.sandbox.spy(),
+        selectTab: base.sandbox.spy(),
+        setItems: base.sandbox.stub().callsFake((obj) => {
+          // Naively simulate what setItems would do calling each object key.
+          Object.keys(obj).forEach((key) => obj[key]());
+        })
+      });
+
+      // Discard generic dashboard, create a new one with adjusted mocks.
+      dashboard = new Dashboard();
+
       const data = {
         value: {
           duplicates: {

We're really pushing the boundaries of how much to mock, but here I think it may make sense because we really want to ensure those imports are (1) happening and (2) used.

Let me know if you need tips on getting even further in to things like asserting on what's called within formatProblems or whatnot...


plugin.observeMetrics({ toJson }).subscribe({
next: () => {},
error: () => {},
Copy link
Member

Choose a reason for hiding this comment

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

GLOBAL TIP: Use base.sandbox.spy() in place of () => {}. It can be asserted on and it's more clear your using a test double.

@@ -1,5 +1,8 @@
"use strict";

const sinon = require("sinon");
Copy link
Member

Choose a reason for hiding this comment

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

GLOBAL: Don't use sinon as a best practice. Instead get spys and stubs from base.sandbox.

@parkerziegler
Copy link
Contributor Author

parkerziegler commented Nov 14, 2018

@ElreyB here are some additional things I'd like to see:

  • Update version to range in format-versions.
  • Add tests for format-versions. Mostly we want some guarantee that our templates match what we expect, given a valid versions object. Let me know if you need help creating a mock for those tests.
  • Add tests for other, untested format-* modules, i.e. format-duplicates, format-problems, and error-serialization.

I think that's about the scope I'd want to see in this PR. I'm also running into issues getting this PR'ed code to run against our inspectpack fixture, so any time you have to investigate that would be great!

context("when package are present", () => {
it("should return a handlebar compile template", () => {
const data = {
packages: {
Copy link
Contributor

Choose a reason for hiding this comment

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

This may be too robust but I want to make sure it hit the pkgNamePath function.

@parkerziegler parkerziegler changed the title [WiP] Start adding regression tests to catch imports of format* utils. Upgrade to inspectpack@4. Add regression tests to catch imports of format* utils. Nov 20, 2018
@parkerziegler
Copy link
Contributor Author

@ryan-roemer This should be ready for re-review. I rebased it down to one commit already (force pushed), so you'll need a clean branch of this locally to test. Let me know if there's anything else you'd like to see in this PR.

and percent is falsy`, () => {
data.value = null;

expect(dashboard.setProgress(data)).to.not.throw;
Copy link
Member

Choose a reason for hiding this comment

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

GLOBAL:

These have to be of the format of "something to call", so:

expect(() => { dashboard.setProgress(data); }).to.not.throw;

unless dashboard.setProgress(data) returns a function to execute, which I don't believe it does.

Copy link
Member

Choose a reason for hiding this comment

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

Note: I was adding comments to everything I saw as "Same comment here.", but there are a lot, so just assume I did that 😛

];

it("can setSizes", () => {
expect(dashboard.setSizes(data)).to.not.throw;
Copy link
Member

Choose a reason for hiding this comment

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

Same comment here.

mockSetItems();
// Discard generic dashboard, create a new one with adjusted mocks.
dashboard = new Dashboard();
expect(dashboard.setSizes(data)).to.not.throw;
Copy link
Member

Choose a reason for hiding this comment

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

Same comment here.

const err = "error";

it("can setSizesError", () => {
expect(dashboard.setSizesError(err)).to.not.throw;
Copy link
Member

Choose a reason for hiding this comment

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

Same comment here.

};

it("can setProblems", () => {
expect(dashboard.setProblems(data)).to.not.throw;
Copy link
Member

Choose a reason for hiding this comment

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

Same comment here.

// Discard generic dashboard, create a new one with adjusted mocks.

dashboard = new Dashboard();
expect(dashboard.setProblems(data)).to.not.throw;
Copy link
Member

Choose a reason for hiding this comment

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

Same comment here.

tapAsync: base.sandbox.stub() // this is us in webpack-dashboard
};
compiler = {
// TODO: ONLY WEBPACK4, but that's what we have in devDeps
Copy link
Member

Choose a reason for hiding this comment

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

Maybe just convert this to a full explanatory comment and remove the TODO. I don't thing we necessarily need to run these unit tests through the different versions...

});

it("should serialize errors when encountered", () => {
base.sandbox.stub(inspectpack, "actions").rejects;
Copy link
Member

Choose a reason for hiding this comment

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

Doesn't this need to be:

base.sandbox.stub(inspectpack, "actions").rejects();

?

If so, is this test working correctly?

Copy link
Member

@ryan-roemer ryan-roemer left a comment

Choose a reason for hiding this comment

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

Great work!!!

I've got lots of comments everywhere, but there mostly straightforward I think, so no re-review needed unless you want one.

Also, quick note that I'm on vacation with free time only here and there, so possibly won't get next opportunity to respond until next week. Feel free to clean up "good enough" and merge here if there are minor outstanding things for me, and we can take up together in follow-on work once I'm back next week.

@parkerziegler parkerziegler force-pushed the task/update-to-inspectpack-4 branch 2 times, most recently from b94b21f to 420bd67 Compare November 24, 2018 18:01
@parkerziegler parkerziegler merged commit ab047f9 into master Nov 25, 2018
@parkerziegler parkerziegler deleted the task/update-to-inspectpack-4 branch November 25, 2018 00:23
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.

3 participants