Improved property matchers concept in e2e-framework

refs: https://github.com/TryGhost/Toolbox/issues/158

- rather than just exposing any, anything and string matching, expose more specific matchers.
- this was triggered by `any(Date)` not working for dates in our API
- it seems poor to match `any(String)` for something we want to be a well formatted date
- establishes the pattern of using our defined matchers instead of requiring any/anything from jest
This commit is contained in:
Hannah Wolfe 2022-02-08 16:36:08 +00:00
parent d7c2759b3f
commit 414344c86c
No known key found for this signature in database
GPG Key ID: AB586C3B5AE5C037
4 changed files with 69 additions and 62 deletions

View File

@ -7,7 +7,7 @@ Object {
"accessibility": null,
"bio": null,
"cover_image": null,
"created_at": Any<String>,
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"email": "test@example.com",
"facebook": null,
"id": "1",
@ -21,7 +21,7 @@ Object {
"status": "active",
"tour": null,
"twitter": null,
"updated_at": Any<String>,
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"url": "http://127.0.0.1:2369/author/joe-bloggs/",
"website": null,
},
@ -35,7 +35,7 @@ Object {
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "434",
"content-type": "application/json; charset=utf-8",
"etag": Any<String>,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Origin, Accept-Encoding",
"x-cache-invalidate": "/*",
"x-powered-by": "Express",
@ -50,7 +50,7 @@ Object {
"context": null,
"details": null,
"help": null,
"id": Any<String>,
"id": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
"message": "Setup has already been completed.",
"property": null,
"type": "NoPermissionError",
@ -65,7 +65,7 @@ Object {
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "201",
"content-type": "application/json; charset=utf-8",
"etag": Any<String>,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Origin, Accept-Encoding",
"x-powered-by": "Express",
}
@ -87,7 +87,7 @@ Object {
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "28",
"content-type": "application/json; charset=utf-8",
"etag": Any<String>,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Origin, Accept-Encoding",
"x-powered-by": "Express",
}
@ -109,7 +109,7 @@ Object {
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "27",
"content-type": "application/json; charset=utf-8",
"etag": Any<String>,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Origin, Accept-Encoding",
"x-powered-by": "Express",
}
@ -122,11 +122,11 @@ Object {
"accessibility": null,
"bio": "bio",
"cover_image": null,
"created_at": Any<String>,
"created_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"email": "test-edit@example.com",
"facebook": null,
"id": "1",
"last_seen": Any<String>,
"last_seen": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"location": "location",
"meta_description": null,
"meta_title": null,
@ -136,7 +136,7 @@ Object {
"status": "active",
"tour": null,
"twitter": null,
"updated_at": Any<String>,
"updated_at": StringMatching /\\\\d\\{4\\}-\\\\d\\{2\\}-\\\\d\\{2\\}T\\\\d\\{2\\}:\\\\d\\{2\\}:\\\\d\\{2\\}\\\\\\.000Z/,
"url": "http://127.0.0.1:2369/author/joe-bloggs/",
"website": null,
},
@ -150,7 +150,7 @@ Object {
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "506",
"content-type": "application/json; charset=utf-8",
"etag": Any<String>,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Origin, Accept-Encoding",
"x-cache-invalidate": "/*",
"x-powered-by": "Express",
@ -173,7 +173,7 @@ Object {
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "32",
"content-type": "application/json; charset=utf-8",
"etag": Any<String>,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Origin, Accept-Encoding",
"x-powered-by": "Express",
}
@ -185,7 +185,7 @@ Object {
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "206",
"content-type": "application/json; charset=utf-8",
"etag": Any<String>,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Origin, Accept-Encoding",
"x-powered-by": "Express",
}
@ -207,7 +207,7 @@ Object {
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "31",
"content-type": "application/json; charset=utf-8",
"etag": Any<String>,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Origin, Accept-Encoding",
"x-powered-by": "Express",
}
@ -229,7 +229,7 @@ Object {
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "51",
"content-type": "application/json; charset=utf-8",
"etag": Any<String>,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Origin, Accept-Encoding",
"x-powered-by": "Express",
}
@ -243,7 +243,7 @@ Object {
"context": "Attempting to create an account with existing email address.",
"details": null,
"help": "Use different email address to register your account.",
"id": Any<String>,
"id": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
"message": "Could not create an account, email is already in use.",
"property": null,
"type": "ValidationError",
@ -258,7 +258,7 @@ Object {
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "328",
"content-type": "application/json; charset=utf-8",
"etag": Any<String>,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Origin, Accept-Encoding",
"x-powered-by": "Express",
}
@ -270,7 +270,7 @@ Object {
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "181",
"content-type": "application/json; charset=utf-8",
"etag": Any<String>,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Origin, Accept-Encoding",
"x-powered-by": "Express",
}
@ -292,7 +292,7 @@ Object {
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "64",
"content-type": "application/json; charset=utf-8",
"etag": Any<String>,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Origin, Accept-Encoding",
"x-powered-by": "Express",
}
@ -306,7 +306,7 @@ Object {
"context": "Password reset link expired.",
"details": null,
"help": "Request a new password reset via the login form.",
"id": Any<String>,
"id": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
"message": "Cannot reset password.",
"property": null,
"type": "BadRequestError",
@ -321,7 +321,7 @@ Object {
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "260",
"content-type": "application/json; charset=utf-8",
"etag": Any<String>,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Origin, Accept-Encoding",
"x-powered-by": "Express",
}
@ -343,7 +343,7 @@ Object {
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "76",
"content-type": "application/json; charset=utf-8",
"etag": Any<String>,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Origin, Accept-Encoding",
"x-powered-by": "Express",
}
@ -357,7 +357,7 @@ Object {
"context": "Invalid password reset link.",
"details": null,
"help": "Check if password reset link has been fully copied or request new password reset via the login form.",
"id": Any<String>,
"id": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
"message": "Cannot reset password.",
"property": null,
"type": "UnauthorizedError",
@ -372,7 +372,7 @@ Object {
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "314",
"content-type": "application/json; charset=utf-8",
"etag": Any<String>,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Origin, Accept-Encoding",
"x-powered-by": "Express",
}
@ -386,7 +386,7 @@ Object {
"context": "Password reset link has already been used.",
"details": null,
"help": "Request a new password reset via the login form.",
"id": Any<String>,
"id": StringMatching /\\[a-f0-9\\]\\{8\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{4\\}-\\[a-f0-9\\]\\{12\\}/,
"message": "Cannot reset password.",
"property": null,
"type": "BadRequestError",
@ -401,7 +401,7 @@ Object {
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "274",
"content-type": "application/json; charset=utf-8",
"etag": Any<String>,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Origin, Accept-Encoding",
"x-powered-by": "Express",
}
@ -415,7 +415,7 @@ Object {
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "2",
"content-type": "application/json; charset=utf-8",
"etag": Any<String>,
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Origin, Accept-Encoding",
"x-powered-by": "Express",
}

View File

@ -1,6 +1,7 @@
const {expect} = require('chai');
const security = require('@tryghost/security');
const {agentProvider, mockManager, fixtureManager, any} = require('../../../utils/e2e-framework');
const {agentProvider, mockManager, fixtureManager, matchers} = require('../../../utils/e2e-framework');
const {anyEtag, anyDate, anyErrorId} = matchers;
const testUtils = require('../../../utils');
const models = require('../../../../core/server/models');
const settingsCache = require('../../../../core/shared/settings-cache');
@ -32,7 +33,7 @@ describe('Authentication API', function () {
.expectStatus(200)
.matchBodySnapshot()
.matchHeaderSnapshot({
etag: any(String)
etag: anyEtag
});
});
@ -59,12 +60,12 @@ describe('Authentication API', function () {
.expectStatus(201)
.matchBodySnapshot({
users: [{
created_at: any(String),
updated_at: any(String)
created_at: anyDate,
updated_at: anyDate
}]
})
.matchHeaderSnapshot({
etag: any(String)
etag: anyEtag
});
// Test our side effects
@ -78,7 +79,7 @@ describe('Authentication API', function () {
.get('authentication/setup')
.matchBodySnapshot()
.matchHeaderSnapshot({
etag: any(String)
etag: anyEtag
});
});
@ -96,11 +97,11 @@ describe('Authentication API', function () {
.expectStatus(403)
.matchBodySnapshot({
errors: [{
id: any(String)
id: anyErrorId
}]
})
.matchHeaderSnapshot({
etag: any(String)
etag: anyEtag
});
});
@ -121,13 +122,13 @@ describe('Authentication API', function () {
.expectStatus(200)
.matchBodySnapshot({
users: [{
created_at: any(String),
last_seen: any(String),
updated_at: any(String)
created_at: anyDate,
last_seen: anyDate,
updated_at: anyDate
}]
})
.matchHeaderSnapshot({
etag: any(String)
etag: anyEtag
});
});
});
@ -145,7 +146,7 @@ describe('Authentication API', function () {
.get('authentication/invitation?email=invalidemail')
.expectStatus(400)
.matchHeaderSnapshot({
etag: any(String)
etag: anyEtag
});
});
@ -155,7 +156,7 @@ describe('Authentication API', function () {
.expectStatus(200)
.matchBodySnapshot()
.matchHeaderSnapshot({
etag: any(String)
etag: anyEtag
});
});
@ -165,7 +166,7 @@ describe('Authentication API', function () {
.expectStatus(200)
.matchBodySnapshot()
.matchHeaderSnapshot({
etag: any(String)
etag: anyEtag
});
});
@ -182,7 +183,7 @@ describe('Authentication API', function () {
})
.expectStatus(404)
.matchHeaderSnapshot({
etag: any(String)
etag: anyEtag
});
});
@ -200,11 +201,11 @@ describe('Authentication API', function () {
.expectStatus(422)
.matchBodySnapshot({
errors: [{
id: any(String)
id: anyErrorId
}]
})
.matchHeaderSnapshot({
etag: any(String)
etag: anyEtag
});
});
@ -222,7 +223,7 @@ describe('Authentication API', function () {
.expectStatus(200)
.matchBodySnapshot()
.matchHeaderSnapshot({
etag: any(String)
etag: anyEtag
});
});
});
@ -267,7 +268,7 @@ describe('Authentication API', function () {
.expectStatus(200)
.matchBodySnapshot()
.matchHeaderSnapshot({
etag: any(String)
etag: anyEtag
});
});
@ -285,11 +286,11 @@ describe('Authentication API', function () {
.expectStatus(401)
.matchBodySnapshot({
errors: [{
id: any(String)
id: anyErrorId
}]
})
.matchHeaderSnapshot({
etag: any(String)
etag: anyEtag
});
});
@ -317,11 +318,11 @@ describe('Authentication API', function () {
.expectStatus(400)
.matchBodySnapshot({
errors: [{
id: any(String)
id: anyErrorId
}]
})
.matchHeaderSnapshot({
etag: any(String)
etag: anyEtag
});
});
@ -346,11 +347,11 @@ describe('Authentication API', function () {
.expectStatus(400)
.matchBodySnapshot({
errors: [{
id: any(String)
id: anyErrorId
}]
})
.matchHeaderSnapshot({
etag: any(String)
etag: anyEtag
});
});
@ -366,7 +367,7 @@ describe('Authentication API', function () {
.expectStatus(200)
.matchBodySnapshot()
.matchHeaderSnapshot({
etag: any(String)
etag: anyEtag
});
});
});
@ -394,7 +395,7 @@ describe('Authentication API', function () {
.expectStatus(200)
.matchBodySnapshot()
.matchHeaderSnapshot({
etag: any(String)
etag: anyEtag
});
// Check side effects

View File

@ -1,5 +1,5 @@
const {any, stringMatching} = require('@tryghost/jest-snapshot');
const {agentProvider} = require('../../../utils/e2e-framework');
const {agentProvider, matchers} = require('../../../utils/e2e-framework');
const {anyString, stringMatching} = matchers;
describe('Site API', function () {
let agent;
@ -17,7 +17,7 @@ describe('Site API', function () {
}
})
.matchHeaderSnapshot({
etag: any(String)
etag: anyString
});
});
});

View File

@ -14,7 +14,7 @@
// The output state checker is responsible for checking the response from the app after performing a request.
const _ = require('lodash');
const {sequence} = require('@tryghost/promise');
const {any, anything, stringMatching} = require('@tryghost/jest-snapshot');
const {any, stringMatching} = require('@tryghost/jest-snapshot');
const fs = require('fs-extra');
const path = require('path');
const os = require('os');
@ -148,7 +148,13 @@ module.exports = {
init: initFixtures,
reset: resetDb
},
any,
anything,
stringMatching
matchers: {
anyString: any(String),
anyDate: stringMatching(/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.000Z/),
anyEtag: stringMatching(/(?:W\/)?"(?:[ !#-\x7E\x80-\xFF]*|\r\n[\t ]|\\.)*"/),
anyObjectId: stringMatching(/[a-f0-9]{24}/),
anyErrorId: stringMatching(/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/),
anyUuid: stringMatching(/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/),
stringMatching
}
};