Added edited property to links api

refs https://github.com/TryGhost/Team/issues/2104

- adds a boolean `edited` property to links api that denotes if the link has been edited
This commit is contained in:
Rishabh 2022-10-20 18:17:44 +05:30
parent ee145ed5b3
commit d7b3721036
4 changed files with 41 additions and 9 deletions

View File

@ -36,10 +36,14 @@ module.exports = class LinkRedirectRepository {
}
fromModel(model) {
// Store if link has been edited
const edited = model.get('created_at')?.getTime() !== model.get('updated_at')?.getTime();
return new LinkRedirect({
id: model.id,
from: new URL(this.#trimLeadingSlash(model.get('from')), this.#urlUtils.urlFor('home', true)),
to: new URL(model.get('to'))
to: new URL(model.get('to')),
edited
});
}

View File

@ -8,6 +8,7 @@ Object {
"clicks": Any<Number>,
},
"link": Object {
"edited": false,
"from": Any<String>,
"link_id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"to": Any<String>,
@ -19,6 +20,7 @@ Object {
"clicks": Any<Number>,
},
"link": Object {
"edited": false,
"from": Any<String>,
"link_id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"to": Any<String>,
@ -30,6 +32,7 @@ Object {
"clicks": Any<Number>,
},
"link": Object {
"edited": false,
"from": Any<String>,
"link_id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"to": Any<String>,
@ -98,7 +101,7 @@ exports[`Links API Can browse all links 2: [headers] 1`] = `
Object {
"access-control-allow-origin": "http://127.0.0.1:2369",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "885",
"content-length": "930",
"content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Accept-Version, Origin, Accept-Encoding",
@ -154,6 +157,7 @@ Object {
"clicks": Any<Number>,
},
"link": Object {
"edited": true,
"from": Any<String>,
"link_id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"to": "https://example.com/subscribe?ref=Test-newsletter",
@ -165,6 +169,7 @@ Object {
"clicks": Any<Number>,
},
"link": Object {
"edited": false,
"from": Any<String>,
"link_id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"to": Any<String>,
@ -176,6 +181,7 @@ Object {
"clicks": Any<Number>,
},
"link": Object {
"edited": false,
"from": Any<String>,
"link_id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"to": Any<String>,
@ -244,7 +250,7 @@ exports[`Links API Can bulk update links with external redirect 4: [headers] 1`]
Object {
"access-control-allow-origin": "http://127.0.0.1:2369",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "885",
"content-length": "929",
"content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Accept-Version, Origin, Accept-Encoding",
@ -300,6 +306,7 @@ Object {
"clicks": Any<Number>,
},
"link": Object {
"edited": false,
"from": Any<String>,
"link_id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"to": Any<String>,
@ -311,6 +318,7 @@ Object {
"clicks": Any<Number>,
},
"link": Object {
"edited": true,
"from": Any<String>,
"link_id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"to": "http://127.0.0.1:2369/blog/emails/test?example=1&ref=Test-newsletter&attribution_type=post&attribution_id=618ba1ffbe2896088840a6df",
@ -322,6 +330,7 @@ Object {
"clicks": Any<Number>,
},
"link": Object {
"edited": true,
"from": Any<String>,
"link_id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"to": "http://127.0.0.1:2369/blog/emails/test?example=1&ref=Test-newsletter&attribution_type=post&attribution_id=618ba1ffbe2896088840a6df",
@ -390,7 +399,7 @@ exports[`Links API Can bulk update multiple links with same site redirect 4: [he
Object {
"access-control-allow-origin": "http://127.0.0.1:2369",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "841",
"content-length": "884",
"content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Accept-Version, Origin, Accept-Encoding",
@ -446,6 +455,7 @@ Object {
"clicks": Any<Number>,
},
"link": Object {
"edited": false,
"from": Any<String>,
"link_id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"to": "https://example.com/subscripe?ref=Test-newsletter",
@ -457,6 +467,7 @@ Object {
"clicks": Any<Number>,
},
"link": Object {
"edited": false,
"from": Any<String>,
"link_id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"to": Any<String>,
@ -468,6 +479,7 @@ Object {
"clicks": Any<Number>,
},
"link": Object {
"edited": false,
"from": Any<String>,
"link_id": StringMatching /\\[a-f0-9\\]\\{24\\}/,
"to": Any<String>,
@ -536,7 +548,7 @@ exports[`Links API Can call bulk update link with 0 matches 4: [headers] 1`] = `
Object {
"access-control-allow-origin": "http://127.0.0.1:2369",
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
"content-length": "885",
"content-length": "930",
"content-type": "application/json; charset=utf-8",
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
"vary": "Accept-Version, Origin, Accept-Encoding",

View File

@ -6,13 +6,20 @@ const matchLink = {
link: {
link_id: anyObjectId,
from: anyString,
to: anyString
to: anyString,
edited: false
},
count: {
clicks: anyNumber
}
};
async function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
describe('Links API', function () {
let agent;
beforeEach(async function () {
@ -41,6 +48,8 @@ describe('Links API', function () {
const postId = siteLink.post_id;
const originalTo = siteLink.link.to;
const filter = `post_id:${postId}+to:'${originalTo}'`;
// Sleep ensures the updated time of the link is different than created
await sleep(1000);
await agent
.put(`links/bulk/?filter=${encodeURIComponent(filter)}`)
.body({
@ -83,14 +92,16 @@ describe('Links API', function () {
...matchLink,
link: {
...matchLink.link,
to: 'http://127.0.0.1:2369/blog/emails/test?example=1&ref=Test-newsletter&attribution_type=post&attribution_id=618ba1ffbe2896088840a6df'
to: 'http://127.0.0.1:2369/blog/emails/test?example=1&ref=Test-newsletter&attribution_type=post&attribution_id=618ba1ffbe2896088840a6df',
edited: true
}
},
{
...matchLink,
link: {
...matchLink.link,
to: 'http://127.0.0.1:2369/blog/emails/test?example=1&ref=Test-newsletter&attribution_type=post&attribution_id=618ba1ffbe2896088840a6df'
to: 'http://127.0.0.1:2369/blog/emails/test?example=1&ref=Test-newsletter&attribution_type=post&attribution_id=618ba1ffbe2896088840a6df',
edited: true
}
}
]
@ -105,6 +116,7 @@ describe('Links API', function () {
const postId = siteLink.post_id;
const originalTo = siteLink.link.to;
const filter = `post_id:${postId}+to:'${originalTo}'`;
await sleep(1000);
await agent
.put(`links/bulk/?filter=${encodeURIComponent(filter)}`)
.body({
@ -146,7 +158,8 @@ describe('Links API', function () {
...matchLink,
link: {
...matchLink.link,
to: 'https://example.com/subscribe?ref=Test-newsletter'
to: 'https://example.com/subscribe?ref=Test-newsletter',
edited: true
}
},
matchLink,

View File

@ -7,6 +7,8 @@ module.exports = class LinkRedirect {
from;
/** @type {URL} */
to;
/** @type {boolean} */
edited;
constructor(data) {
if (!data.id) {
@ -19,5 +21,6 @@ module.exports = class LinkRedirect {
this.from = data.from;
this.to = data.to;
this.edited = !!data.edited;
}
};