Failing #10 User Story on Bar Chart Challenge

So I have the Bar Chart project for the Data Viz challenge ALMOST working, and I’m failing user story #10. I’ve gone through other examples for this in the forum, and I’m not repeating any obvious mistakes that I can see, and if the last value is any indication, this isn’t some off-by-one error. My code is at: https://codepen.io/dylanesque39/pen/jRveKq

EDIT: I looked at GitHub on a whim, and it looks like there’s a known issue with this particular test (D3 project Bar Chart: Test not aligned with description. · Issue #39299 · freeCodeCamp/freeCodeCamp · GitHub). I’m considering my current solution ‘good enough for govt work’, but I’d love to hear about how anybody else dealt with this quirk if you ran into it.

When I zoom in on your chart and check the bars versus the axis (check around 2015 for example), the bar that aligns with the year tick is the bar for Q2 (April), not Q1 (January), so it really looks like an off by one error.

If you change your x coordinate attribute code to

        .attr('x', (d, i) => {
          console.log(`scale: ${xScale(parseTime(d[0]))}`);
          console.log(`calculated: ${i*barWidth}`);
          return i * barWidth;
        })

you will notice that the numbers don’t match and get worse as they increase. You could get around this with an integer bar width. Regardless, there is an alignment issue.

That doesn’t add up, when I mouse over the very first bar, the data that appears there matches the first value in the dataset, ditto for the last bar, so I don’t see how those values could be off, especially in the face of a known issue with the test.

Run the code I posted and look at the results in the console. Or, look at the coordinates of your bars (Q1 for every fifth year) and of the five year ticks. The numbers do not match, so your bars are not in alignment with the axis. Further, in chrome 90, your Q1 bars are to the left of every 5 year tick on the x-axis.

The linked issue was published before I did a solution to this challenge and I believe would only cause problems if you didn’t have the year in your ticks and had something else, like a date object, since when getTickValue() gets called with the dataType = year, it gets the default case, which parses whatever the year value is as a float and parsing a Date() as a float would be problematic. But, if you examine your ticks, they have just the year and should not be affected by this issue. Further, you have the same exact attributes on your ticks and your bars that I do on my working solution, you just don’t have matching coordinates as indicated by the code snippet above.

I think I see what you’re saying, but it’s unclear what the optimum fix for this is: I can rein in the scaling but slapping .toFixed() on the barWidth, but I don’t see how to fix this without running into incongrously sized bars/padding after the bars.

EDIT: Now this is strange: I changed the value of the x attr from i * barWidth to xScale(xAccessor(d)), and the alignment is now behaving as expected on close inspection (if I hover over the 1995 tick, for example, the value shown is 1-1-1995). So, it looks like your assessment of the issue was correct but the testing bug is still in play? I guess that will be clearer after I knock out an approved PR for that issue.

To me, the test doesn’t really have a bug. It just checks ticks which are every five years, so I would expect the tick to have a year as its attribute. It’s confusing, because some people try to use a date string or date object instead, and the test doesn’t check for that, so a simple try-catch in the default case of getTickValue() that tries to parse a date string or object first and then on error parses the float for the year could do the trick. But, it’s hard to anticipate what everyone will try to use as the tick attribute so the easiest fix is as mentioned in the issue: specify in the description to just use years for the ticks.

The effect of changing the x-attr like this is expected behavior since you defined xScale with parsed date objects. Calculating positions with date objects from the scale should then lead to better alignment than calculating them manually with another method.

The bug in your chart is way more subtle. If you change the bottom of your script as follows:

// barChart();
(async function () {
  await barChart();
  const axis = await document.querySelector('#x-axis');
  const ticks = await axis.querySelectorAll('.tick');

  for (let i = 0; i < ticks.length; i++) {
    console.log(ticks[i]);
    console.log(ticks[i].querySelector('text').innerHTML);
  }
})();

(which is just some code from the test to see what exactly is happening during the test), you’ll find the problem: you attached your x-label to the x-axis and the test believes it’s a five year tick.

You’ll also notice that your last bar hangs off the end of the axis because the axis is three months too short.

This only makes me more confused at this error: looking at the output of this example code, it’s not a tick on the axis that throws the error, it’s the text label of the axis. The last output of the console.log is:

<text x="365.55" y="30" class="tick" fill="black" style="font-size: 1.4em;">Year</text>

If I remove the .text('Year') from the label generating expression, It just returns a blank text element that throws the same error.

The solution, for anybody else who runs into this issue:

Version 5 (at the latest, since that’s what I’m using) of D3 automatically appends the ‘tick’ class to axis labels. I was manually appending the ‘tick’ class to my x-axis label, causing this test to fail.