Skip to content
This repository has been archived by the owner on Apr 3, 2019. It is now read-only.

refactor(token): remove ability to pass createdAt to Token.create #1764

Merged
merged 1 commit into from Mar 27, 2017

Conversation

seanmonstar
Copy link
Contributor

This exists to support passing _createdAt as a query parameter, but
only for our tests. Those tests were to exercise our response
validation in a way that the lastAccessTime allows a value of 0. That
validation was fixed long ago, and supporting this hacky parameter has
done nothing but plague us since.

Burn the heretic.

/cc @philbooth @rfk

var now = Date.now() - 1
return Token.createNewToken(Token, { createdAt: now }).then(token => {
assert.equal(token.createdAt, now, 'token.createdAt is correct')
assert.notEqual(token.createdAt, now, 'token.createdAt is new')
Copy link
Contributor

Choose a reason for hiding this comment

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

The anally-retentive pedant inside me thinks this should assert that token.createdAt > now rather than just asserting inequality.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Mocha pretty prints equal and notEqual assertions better than it can ok assertions. 🤷‍♂️

@@ -41,41 +41,13 @@ module.exports = function (log, config, random, P, hkdf, Bundle, error) {
this.createdAt = details.createdAt || 0
Copy link
Contributor

@philbooth philbooth Mar 24, 2017

Choose a reason for hiding this comment

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

Every time I see this line, it confuses me. Can someone remind me why we need || 0 here again please?

Copy link
Contributor

Choose a reason for hiding this comment

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

(I mean, as opposed to || Date.now())

Copy link
Contributor

Choose a reason for hiding this comment

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

Most recently, because the API test client in ./tests/client/ calls fromHex without specifying the createdAt time, so we gotta default it to something, and zero is much safer than e.g. the current time.

Of course the right answer might be to fix those damn tests to use the API correctly, or to use a simpler wrapper around it.

Copy link
Contributor

Choose a reason for hiding this comment

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

Defaulting to Date.now might give us back that bug with tokens that never expire.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah yeah, thanks.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There's this perhaps unintuitive contract in the Token API, which is:

  • Token.create is for generating brand new tokens, and so createdAt = Date.now()
  • Token.from (fromHex, fromId) is for building a pre-existing Token, and so createdAt should definitely be provided
  • new Token doesn't know which context it is being used in, so just defaults to believing the token is from 1969 until told otherwise.

)
}
)

Copy link
Contributor

Choose a reason for hiding this comment

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

Something about deleting all three of these tests sits uneasily with me. I feel like, to some extent, they were legitimately asserting edge-case behaviour of the devices API.

Now that the tests are run in-process, is it possible to retain some of this coverage by mocking the result of Date.now()? Do we want to do that or am I being over-cautious?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It all depends on what exactly we hoped these were testing. My Pull Request CSI suggested that this was added as a regression test that our joi validation of lastAccessTime allowed a value of 0. This was the main reason for it being a "remote" test, so that it went through response validation.

If we want to still test that, a simple unit test in local should be pretty easy:

const schema = getRoute('/accounts/devices').config.response.schema.lastAccessTime
assert(!Joi.validate({ lastAccessTime: 0 }, schema).error)

If we were testing specific behavior of handlers, and not response validation, that can probably also become local tests, with the edges cases specifically mocked in.

Copy link
Contributor

Choose a reason for hiding this comment

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

It all depends on what exactly we hoped these were testing. My Pull Request CSI suggested that this was added as a regression test that our joi validation of lastAccessTime allowed a value of 0.

That's definitely case for the first one, above, but the two underneath look different to me. It seems like they're testing how the guts of the devices endpoint behaves when it encounters odd session tokens. Is that something we're definitely happy to lose coverage of?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can definitely adapt these tests to not pass _createdAt, but I don't fully understand what they are testing. Is it the behavior of updateDevice? The devices get route? I'll be sure to update the test description too once we know XD

Copy link
Contributor

@philbooth philbooth Mar 25, 2017

Choose a reason for hiding this comment

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

I might be wrong about all this of course, but for what it's worth I read them as testing the behaviour of GET /account/devices. Definitely don't keep them if you don't think they add value though. I just wanted to make sure we'd considered them is all.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I've audited what these tests were doing:

  • sessionToken.lastAccessTime === 0: Testing that the route allows returning a last access time of 0, because of the default value in the DB of 0. I've added a local unit test making asserting that lastAccessTime: 0 passes the Joi validation.
  • sessionToken.lastAccessTime === -1: Simply is testing that /account/create fails with _createdAt=-1. Since that parameter is not even accepted anymore, test is no longer needed.
  • sessionToken.lastAccessTime === FUTURE: The access time is not adjusted anywhere in devices.upsert or devices.get routes, so this was only testing the initial creation of a device with a sessionToken from the future. The only code that adjusted the timestamp if it was in the future was in optionallyOverrideCreatedAt. So, the test was exercising our optional override, which has also been removed in this PR.

I believe the tests now accurately reflect the world.

@philbooth
Copy link
Contributor

I support this change and will be glad to see the back of _createdAt. There's one question inline about whether we should keep some of the test coverage but, either way, I am r+.

This exists to support passing `_createdAt` as a query parameter, but
only for our tests. Those tests were to exercise our response
validation in a way that the `lastAccessTime` allows a value of 0. That
validation was fixed long ago, and supporting this hacky parameter has
done nothing but plague us since.

Burn the heretic.
@seanmonstar seanmonstar merged commit 886aa82 into master Mar 27, 2017
@seanmonstar seanmonstar deleted the burn-created-at branch March 27, 2017 22:36
@rfk rfk added this to the FxA-0: quality milestone Apr 12, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants