From 7468c152d210f684979a29de5dd22559ee017034 Mon Sep 17 00:00:00 2001
From: Felipe Barso <77860630+aprendendofelipe@users.noreply.github.com>
Date: Thu, 11 Jul 2024 16:31:46 -0300
Subject: [PATCH 1/4] feat(ad content): allows to create ad content
---
models/authorization.js | 1 +
models/balance.js | 5 +-
models/content.js | 46 +++++-
models/validator.js | 10 ++
pages/api/v1/contents/index.public.js | 1 +
tests/constants-for-tests.js | 1 +
.../integration/api/v1/contents/post.test.js | 145 +++++++++++++++++-
tests/orchestrator.js | 1 +
8 files changed, 205 insertions(+), 5 deletions(-)
diff --git a/models/authorization.js b/models/authorization.js
index d55fcca20..417edbf49 100644
--- a/models/authorization.js
+++ b/models/authorization.js
@@ -118,6 +118,7 @@ function filterInput(user, feature, input, target) {
title: input.title,
body: input.body,
status: input.status,
+ type: input.type,
source_url: input.source_url,
};
}
diff --git a/models/balance.js b/models/balance.js
index f04a0a45c..008ea8398 100644
--- a/models/balance.js
+++ b/models/balance.js
@@ -49,6 +49,9 @@ async function findAllByOriginatorId(originatorId, options) {
async function create({ balanceType, recipientId, amount, originatorType, originatorId }, options = {}) {
const tableName = tableNameMap[balanceType] || tableNameMap.default;
const hasBalanceTypeColum = balanceType.startsWith('content:tabcoin');
+ const totalBalanceFunction = sqlFunctionMap[balanceType] || sqlFunctionMap.default;
+
+ const returning = options.withBalance ? `*, ${totalBalanceFunction}($1) as total` : '*';
const query = {
text: `
@@ -56,7 +59,7 @@ async function create({ balanceType, recipientId, amount, originatorType, origin
(recipient_id, amount, originator_type, originator_id${hasBalanceTypeColum ? ', balance_type' : ''})
VALUES
($1, $2, $3, $4${hasBalanceTypeColum ? ', $5' : ''})
- RETURNING * ;
+ RETURNING ${returning};
`,
values: [recipientId, amount, originatorType, originatorId],
};
diff --git a/models/content.js b/models/content.js
index e3ebc8396..9181c6559 100644
--- a/models/content.js
+++ b/models/content.js
@@ -1,7 +1,7 @@
import { randomUUID as uuidV4 } from 'node:crypto';
import slug from 'slug';
-import { ForbiddenError, ValidationError } from 'errors';
+import { ForbiddenError, UnprocessableEntityError, ValidationError } from 'errors';
import database from 'infra/database.js';
import balance from 'models/balance.js';
import pagination from 'models/pagination.js';
@@ -113,6 +113,7 @@ async function findAll(values = {}, options = {}) {
contents.title,
${!values.attributes?.exclude?.includes('body') ? 'contents.body,' : ''}
contents.status,
+ contents.type,
contents.source_url,
contents.created_at,
contents.updated_at,
@@ -286,6 +287,11 @@ async function create(postedContent, options = {}) {
transaction: options.transaction,
});
+ await updateTabCashBalance(null, newContent, {
+ eventId: options.eventId,
+ transaction: options.transaction,
+ });
+
const tabcoinsCount = await balance.getContentTabcoinsCreditDebit(
{
recipientId: newContent.id,
@@ -317,8 +323,8 @@ async function create(postedContent, options = {}) {
),
inserted_content as (
INSERT INTO
- contents (id, parent_id, owner_id, slug, title, body, status, source_url, published_at, path)
- SELECT $1, $2, $3, $4, $5, $6, $7, $8, $9, parent.child_path
+ contents (id, parent_id, owner_id, slug, title, body, status, source_url, published_at, type, path)
+ SELECT $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, parent.child_path
FROM parent
RETURNING *
)
@@ -330,6 +336,7 @@ async function create(postedContent, options = {}) {
inserted_content.title,
inserted_content.body,
inserted_content.status,
+ inserted_content.type,
inserted_content.source_url,
inserted_content.created_at,
inserted_content.updated_at,
@@ -355,6 +362,7 @@ async function create(postedContent, options = {}) {
content.status,
content.source_url,
content.published_at,
+ content.type,
],
};
@@ -440,6 +448,7 @@ function validateCreateSchema(content) {
title: 'optional',
body: 'required',
status: 'required',
+ content_type: 'optional',
source_url: 'optional',
});
@@ -602,6 +611,36 @@ async function creditOrDebitTabCoins(oldContent, newContent, options = {}) {
}
}
+async function updateTabCashBalance(oldContent, newContent, options = {}) {
+ if (newContent.type === 'content') {
+ return;
+ }
+
+ const tabCashToDebitFromUser = -100;
+
+ const balanceResult = await balance.create(
+ {
+ balanceType: 'user:tabcash',
+ recipientId: newContent.owner_id,
+ amount: tabCashToDebitFromUser,
+ originatorType: options.eventId ? 'event' : 'content',
+ originatorId: options.eventId ? options.eventId : newContent.id,
+ },
+ {
+ transaction: options.transaction,
+ withBalance: true,
+ },
+ );
+
+ if (balanceResult.total < 0) {
+ throw new UnprocessableEntityError({
+ message: `Não foi possível criar a publicação.`,
+ action: `Você precisa de pelo menos ${Math.abs(tabCashToDebitFromUser)} TabCash para realizar esta ação.`,
+ errorLocationCode: 'MODEL:CONTENT:UPDATE_TABCASH:NOT_ENOUGH',
+ });
+ }
+}
+
async function update(contentId, postedContent, options = {}) {
const validPostedContent = validateUpdateSchema(postedContent);
@@ -674,6 +713,7 @@ async function update(contentId, postedContent, options = {}) {
updated_content.title,
updated_content.body,
updated_content.status,
+ updated_content.type,
updated_content.source_url,
updated_content.created_at,
updated_content.updated_at,
diff --git a/models/validator.js b/models/validator.js
index dc55e6a6e..7a130f70b 100644
--- a/models/validator.js
+++ b/models/validator.js
@@ -251,6 +251,16 @@ const schemas = {
});
},
+ content_type: function () {
+ return Joi.object({
+ type: Joi.string()
+ .trim()
+ .valid('content', 'ad')
+ .default('content')
+ .when('$required.content_type', { is: 'required', then: Joi.required(), otherwise: Joi.optional() }),
+ });
+ },
+
source_url: function () {
return Joi.object({
source_url: Joi.string()
diff --git a/pages/api/v1/contents/index.public.js b/pages/api/v1/contents/index.public.js
index a3a2166ec..24a856051 100644
--- a/pages/api/v1/contents/index.public.js
+++ b/pages/api/v1/contents/index.public.js
@@ -89,6 +89,7 @@ function postValidationHandler(request, response, next) {
title: 'optional',
body: 'required',
status: 'optional',
+ content_type: 'optional',
source_url: 'optional',
});
diff --git a/tests/constants-for-tests.js b/tests/constants-for-tests.js
index 731174eb1..484e9ec5f 100644
--- a/tests/constants-for-tests.js
+++ b/tests/constants-for-tests.js
@@ -1,2 +1,3 @@
+export const defaultTabCashForAdCreation = 100;
export const maxSlugLength = 160;
export const maxTitleLength = 255;
diff --git a/tests/integration/api/v1/contents/post.test.js b/tests/integration/api/v1/contents/post.test.js
index 692d94ae7..8ddfe043e 100644
--- a/tests/integration/api/v1/contents/post.test.js
+++ b/tests/integration/api/v1/contents/post.test.js
@@ -1,7 +1,8 @@
import { version as uuidVersion } from 'uuid';
import database from 'infra/database';
-import { maxSlugLength, maxTitleLength } from 'tests/constants-for-tests';
+import content from 'models/content';
+import { defaultTabCashForAdCreation, maxSlugLength, maxTitleLength } from 'tests/constants-for-tests';
import orchestrator from 'tests/orchestrator.js';
import RequestBuilder from 'tests/request-builder';
@@ -2900,5 +2901,147 @@ describe('POST /api/v1/contents', () => {
expect(userResponseBody.tabcash).toEqual(0);
});
});
+
+ describe('With "type: ad"', () => {
+ test('Should be able to create "ad" type content', async () => {
+ const contentsRequestBuilder = new RequestBuilder('/api/v1/contents');
+ const defaultUser = await contentsRequestBuilder.buildUser();
+
+ orchestrator.createBalance({
+ balanceType: 'user:tabcash',
+ recipientId: defaultUser.id,
+ amount: defaultTabCashForAdCreation,
+ });
+
+ const { response, responseBody } = await contentsRequestBuilder.post({
+ title: 'Ad title',
+ body: 'Ad body',
+ status: 'published',
+ type: 'ad',
+ source_url: 'https://www.tabnews.com.br',
+ });
+
+ const createdAdContent = await content.findOne({ where: { id: responseBody.id } });
+
+ expect.soft(createdAdContent.type).toBe('ad');
+ expect.soft(response.status).toBe(201);
+
+ expect(responseBody).toStrictEqual({
+ id: responseBody.id,
+ owner_id: defaultUser.id,
+ parent_id: null,
+ slug: 'ad-title',
+ title: 'Ad title',
+ body: 'Ad body',
+ status: 'published',
+ source_url: 'https://www.tabnews.com.br',
+ created_at: responseBody.created_at,
+ updated_at: responseBody.updated_at,
+ published_at: responseBody.published_at,
+ deleted_at: null,
+ tabcoins: 0,
+ tabcoins_credit: 0,
+ tabcoins_debit: 0,
+ owner_username: defaultUser.username,
+ });
+
+ expect(uuidVersion(responseBody.id)).toBe(4);
+ expect(Date.parse(responseBody.created_at)).not.toBeNaN();
+ expect(Date.parse(responseBody.updated_at)).not.toBeNaN();
+ });
+
+ test(`Should debit ${defaultTabCashForAdCreation} TabCash`, async () => {
+ const contentsRequestBuilder = new RequestBuilder('/api/v1/contents');
+ const usersRequestBuilder = new RequestBuilder('/api/v1/users');
+ const defaultUser = await contentsRequestBuilder.buildUser();
+
+ orchestrator.createBalance({
+ balanceType: 'user:tabcash',
+ recipientId: defaultUser.id,
+ amount: 1_000 + defaultTabCashForAdCreation,
+ });
+
+ const { response: contentResponse } = await contentsRequestBuilder.post({
+ title: 'Ad title',
+ body: 'Ad body',
+ status: 'published',
+ type: 'ad',
+ });
+
+ const { responseBody: userResponseBody } = await usersRequestBuilder.get(`/${defaultUser.username}`);
+
+ expect.soft(contentResponse.status).toBe(201);
+ expect(userResponseBody.tabcash).toBe(1_000);
+ });
+
+ test(`Should not be able to create without enough TabCash`, async () => {
+ const contentsRequestBuilder = new RequestBuilder('/api/v1/contents');
+ const usersRequestBuilder = new RequestBuilder('/api/v1/users');
+ const defaultUser = await contentsRequestBuilder.buildUser();
+
+ orchestrator.createBalance({
+ balanceType: 'user:tabcash',
+ recipientId: defaultUser.id,
+ amount: defaultTabCashForAdCreation - 1,
+ });
+
+ const { response, responseBody } = await contentsRequestBuilder.post({
+ title: 'Ad title',
+ body: 'Ad body',
+ status: 'published',
+ type: 'ad',
+ });
+
+ expect.soft(response.status).toBe(422);
+
+ expect(responseBody).toStrictEqual({
+ name: 'UnprocessableEntityError',
+ message: 'Não foi possível criar a publicação.',
+ action: `Você precisa de pelo menos ${defaultTabCashForAdCreation} TabCash para realizar esta ação.`,
+ status_code: 422,
+ error_id: responseBody.error_id,
+ request_id: responseBody.request_id,
+ error_location_code: 'MODEL:CONTENT:UPDATE_TABCASH:NOT_ENOUGH',
+ });
+
+ const { responseBody: userResponseBody } = await usersRequestBuilder.get(`/${defaultUser.username}`);
+
+ expect(userResponseBody.tabcash).toBe(defaultTabCashForAdCreation - 1);
+ });
+ });
+
+ describe('With invalid "type"', () => {
+ test('Should not be able to POST with invalid "type"', async () => {
+ const contentsRequestBuilder = new RequestBuilder('/api/v1/contents');
+ const defaultUser = await contentsRequestBuilder.buildUser();
+
+ orchestrator.createBalance({
+ balanceType: 'user:tabcash',
+ recipientId: defaultUser.id,
+ amount: defaultTabCashForAdCreation,
+ });
+
+ const { response, responseBody } = await contentsRequestBuilder.post({
+ title: 'Ad title',
+ body: 'Ad body',
+ status: 'published',
+ type: 'invalid_type',
+ });
+
+ expect.soft(response.status).toBe(400);
+
+ expect(responseBody).toStrictEqual({
+ name: 'ValidationError',
+ message: '"type" deve possuir um dos seguintes valores: "content", "ad".',
+ action: 'Ajuste os dados enviados e tente novamente.',
+ status_code: 400,
+ error_id: responseBody.error_id,
+ request_id: responseBody.request_id,
+ error_location_code: 'MODEL:VALIDATOR:FINAL_SCHEMA',
+ key: 'type',
+ type: 'any.only',
+ });
+ });
+ });
});
});
diff --git a/tests/orchestrator.js b/tests/orchestrator.js
index c880c380e..d1c62eea5 100644
--- a/tests/orchestrator.js
+++ b/tests/orchestrator.js
@@ -216,6 +216,7 @@ async function createContent(contentObject) {
slug: contentObject?.slug || undefined,
body: contentObject?.body || faker.lorem.paragraphs(5),
status: contentObject?.status || 'draft',
+ type: contentObject?.type || 'content',
source_url: contentObject?.source_url || undefined,
},
{
From e42c6454f9cce2a37ab8dcb35d628ba0a56f935a Mon Sep 17 00:00:00 2001
From: Felipe Barso <77860630+aprendendofelipe@users.noreply.github.com>
Date: Thu, 11 Jul 2024 16:32:36 -0300
Subject: [PATCH 2/4] feat(ad content): prevent creation of ad content with
`parent_id`
Adds a test case to ensure that ad content cannot be created with a "parent_id" parameter.
This prevents potential issues with the content hierarchy.
---
.../integration/api/v1/contents/post.test.js | 53 +++++++++++++++++++
1 file changed, 53 insertions(+)
diff --git a/tests/integration/api/v1/contents/post.test.js b/tests/integration/api/v1/contents/post.test.js
index 8ddfe043e..18cf21890 100644
--- a/tests/integration/api/v1/contents/post.test.js
+++ b/tests/integration/api/v1/contents/post.test.js
@@ -3008,6 +3008,59 @@ describe('POST /api/v1/contents', () => {
expect(userResponseBody.tabcash).toBe(defaultTabCashForAdCreation - 1);
});
+
+ test('Should not be able to create with "parent_id"', async () => {
+ const contentsRequestBuilder = new RequestBuilder('/api/v1/contents');
+ const defaultUser = await contentsRequestBuilder.buildUser();
+
+ const { responseBody: rootContent } = await contentsRequestBuilder.post({
+ title: 'Root title',
+ body: 'Root body',
+ status: 'published',
+ });
+
+ orchestrator.createBalance({
+ balanceType: 'user:tabcash',
+ recipientId: defaultUser.id,
+ amount: defaultTabCashForAdCreation,
+ });
+
+ const { response, responseBody } = await contentsRequestBuilder.post({
+ title: 'Ad title',
+ body: 'Ad body',
+ status: 'published',
+ type: 'ad',
+ parent_id: rootContent.id,
+ });
+
+ const createdAdContent = await content.findOne({ where: { id: responseBody.id } });
+
+ expect.soft(createdAdContent.type).toBe('content');
+ expect.soft(response.status).toBe(201);
+
+ expect(responseBody).toStrictEqual({
+ id: responseBody.id,
+ owner_id: defaultUser.id,
+ parent_id: rootContent.id,
+ slug: 'ad-title',
+ title: 'Ad title',
+ body: 'Ad body',
+ status: 'published',
+ source_url: null,
+ created_at: responseBody.created_at,
+ updated_at: responseBody.updated_at,
+ published_at: responseBody.published_at,
+ deleted_at: null,
+ tabcoins: 0,
+ tabcoins_credit: 0,
+ tabcoins_debit: 0,
+ owner_username: defaultUser.username,
+ });
+
+ expect(uuidVersion(responseBody.id)).toBe(4);
+ expect(Date.parse(responseBody.created_at)).not.toBeNaN();
+ expect(Date.parse(responseBody.updated_at)).not.toBeNaN();
+ });
});
describe('With invalid "type"', () => {
From 557835add1a1fc706500d7bbbf8b6c09492a59e6 Mon Sep 17 00:00:00 2001
From: Felipe Barso <77860630+aprendendofelipe@users.noreply.github.com>
Date: Thu, 11 Jul 2024 16:48:32 -0300
Subject: [PATCH 3/4] feat(ad content): do not credit users with `TabCoins` for
creating ads
Prevent the crediting of TabCoins to the user if the "type" of the new content is not "content".
---
models/content.js | 5 ++++
.../integration/api/v1/contents/post.test.js | 28 +++++++++++++++++++
2 files changed, 33 insertions(+)
diff --git a/models/content.js b/models/content.js
index 9181c6559..11f2ed632 100644
--- a/models/content.js
+++ b/models/content.js
@@ -559,6 +559,11 @@ async function creditOrDebitTabCoins(oldContent, newContent, options = {}) {
});
}
+ // We should not credit TabCoins to the user if the "type" is not "content".
+ if (newContent.type !== 'content') {
+ userEarnings = 0;
+ }
+
// We should not credit if the content has little or no value.
if (newContent.body.split(/[a-z]{5,}/i, 6).length < 6) return;
diff --git a/tests/integration/api/v1/contents/post.test.js b/tests/integration/api/v1/contents/post.test.js
index 18cf21890..78fdae1b1 100644
--- a/tests/integration/api/v1/contents/post.test.js
+++ b/tests/integration/api/v1/contents/post.test.js
@@ -3061,6 +3061,34 @@ describe('POST /api/v1/contents', () => {
expect(Date.parse(responseBody.created_at)).not.toBeNaN();
expect(Date.parse(responseBody.updated_at)).not.toBeNaN();
});
+
+ test('Should not credit TabCoins to the user', async () => {
+ const contentsRequestBuilder = new RequestBuilder('/api/v1/contents');
+ const usersRequestBuilder = new RequestBuilder('/api/v1/users');
+ const defaultUser = await contentsRequestBuilder.buildUser();
+ await orchestrator.createPrestige(defaultUser.id, { rootPrestigeNumerator: 2, rootPrestigeDenominator: 10 });
+
+ orchestrator.createBalance({
+ balanceType: 'user:tabcash',
+ recipientId: defaultUser.id,
+ amount: defaultTabCashForAdCreation,
+ });
+
+ const { response: contentResponse, responseBody: contentResponseBody } = await contentsRequestBuilder.post({
+ title: 'Title',
+ body: 'Relevant text needs to contain a good amount of words',
+ status: 'published',
+ type: 'ad',
+ });
+
+ const { responseBody: userResponseBody } = await usersRequestBuilder.get(`/${defaultUser.username}`);
+
+ expect.soft(contentResponse.status).toBe(201);
+ expect(contentResponseBody.tabcoins).toBe(1);
+ expect(contentResponseBody.type).toBe('ad');
+ expect(userResponseBody.tabcoins).toBe(0);
+ expect(userResponseBody.tabcash).toBe(0);
+ });
});
describe('With invalid "type"', () => {
From 9a22f91e5c8946a2f10fee82080ce15bc12a0bc6 Mon Sep 17 00:00:00 2001
From: Felipe Barso <77860630+aprendendofelipe@users.noreply.github.com>
Date: Thu, 11 Jul 2024 17:22:14 -0300
Subject: [PATCH 4/4] feat(content): add `type` field to public content schema
---
models/validator.js | 1 +
.../[username]/[slug]/children/get.test.js | 11 +++++
.../v1/contents/[username]/[slug]/get.test.js | 5 +++
.../[username]/[slug]/parent/get.test.js | 5 +++
.../contents/[username]/[slug]/patch.test.js | 27 +++++++++++
.../[username]/[slug]/root/get.test.js | 6 +++
.../api/v1/contents/[username]/get.test.js | 14 ++++++
tests/integration/api/v1/contents/get.test.js | 8 ++++
.../integration/api/v1/contents/post.test.js | 45 ++++++++++++++++---
9 files changed, 115 insertions(+), 7 deletions(-)
diff --git a/models/validator.js b/models/validator.js
index 7a130f70b..81201207f 100644
--- a/models/validator.js
+++ b/models/validator.js
@@ -492,6 +492,7 @@ const schemas = {
'title',
'body',
'status',
+ 'content_type',
'source_url',
'created_at',
'updated_at',
diff --git a/tests/integration/api/v1/contents/[username]/[slug]/children/get.test.js b/tests/integration/api/v1/contents/[username]/[slug]/children/get.test.js
index 311cd6e37..4914d374d 100644
--- a/tests/integration/api/v1/contents/[username]/[slug]/children/get.test.js
+++ b/tests/integration/api/v1/contents/[username]/[slug]/children/get.test.js
@@ -154,6 +154,7 @@ describe('GET /api/v1/contents/[username]/[slug]/children', () => {
tabcoins_credit: 0,
tabcoins_debit: 0,
status: childBranchBLevel1.status,
+ type: 'content',
source_url: childBranchBLevel1.source_url,
created_at: childBranchBLevel1.created_at.toISOString(),
updated_at: childBranchBLevel1.updated_at.toISOString(),
@@ -172,6 +173,7 @@ describe('GET /api/v1/contents/[username]/[slug]/children', () => {
tabcoins_credit: 0,
tabcoins_debit: 0,
status: childBranchBLevel2Content1.status,
+ type: 'content',
source_url: childBranchBLevel2Content1.source_url,
created_at: childBranchBLevel2Content1.created_at.toISOString(),
updated_at: childBranchBLevel2Content1.updated_at.toISOString(),
@@ -192,6 +194,7 @@ describe('GET /api/v1/contents/[username]/[slug]/children', () => {
tabcoins_credit: 0,
tabcoins_debit: 0,
status: childBranchBLevel2Content2.status,
+ type: 'content',
source_url: childBranchBLevel2Content2.source_url,
created_at: childBranchBLevel2Content2.created_at.toISOString(),
updated_at: childBranchBLevel2Content2.updated_at.toISOString(),
@@ -212,6 +215,7 @@ describe('GET /api/v1/contents/[username]/[slug]/children', () => {
title: childBranchALevel1.title,
body: childBranchALevel1.body,
status: childBranchALevel1.status,
+ type: 'content',
tabcoins: 1,
tabcoins_credit: 0,
tabcoins_debit: 0,
@@ -230,6 +234,7 @@ describe('GET /api/v1/contents/[username]/[slug]/children', () => {
title: childBranchALevel2.title,
body: childBranchALevel2.body,
status: childBranchALevel2.status,
+ type: 'content',
tabcoins: 1,
tabcoins_credit: 0,
tabcoins_debit: 0,
@@ -251,6 +256,7 @@ describe('GET /api/v1/contents/[username]/[slug]/children', () => {
tabcoins_credit: 0,
tabcoins_debit: 0,
status: childBranchALevel3.status,
+ type: 'content',
source_url: childBranchALevel3.source_url,
created_at: childBranchALevel3.created_at.toISOString(),
updated_at: childBranchALevel3.updated_at.toISOString(),
@@ -346,6 +352,7 @@ describe('GET /api/v1/contents/[username]/[slug]/children', () => {
title: childBranchBLevel2Content2.title,
body: childBranchBLevel2Content2.body,
status: childBranchBLevel2Content2.status,
+ type: 'content',
tabcoins: 1,
tabcoins_credit: 0,
tabcoins_debit: 0,
@@ -366,6 +373,7 @@ describe('GET /api/v1/contents/[username]/[slug]/children', () => {
title: childBranchBLevel2Content1.title,
body: childBranchBLevel2Content1.body,
status: childBranchBLevel2Content1.status,
+ type: 'content',
tabcoins: 0,
tabcoins_credit: 0,
tabcoins_debit: 0,
@@ -436,6 +444,7 @@ describe('GET /api/v1/contents/[username]/[slug]/children', () => {
tabcoins_credit: 2,
tabcoins_debit: -1,
status: childBranchBLevel1.status,
+ type: 'content',
source_url: childBranchBLevel1.source_url,
created_at: childBranchBLevel1.created_at.toISOString(),
updated_at: childBranchBLevel1.updated_at.toISOString(),
@@ -453,6 +462,7 @@ describe('GET /api/v1/contents/[username]/[slug]/children', () => {
title: childBranchALevel1.title,
body: childBranchALevel1.body,
status: childBranchALevel1.status,
+ type: 'content',
tabcoins: 1,
tabcoins_credit: 0,
tabcoins_debit: 0,
@@ -471,6 +481,7 @@ describe('GET /api/v1/contents/[username]/[slug]/children', () => {
title: childBranchALevel2.title,
body: childBranchALevel2.body,
status: childBranchALevel2.status,
+ type: 'content',
tabcoins: 5,
tabcoins_credit: 4,
tabcoins_debit: 0,
diff --git a/tests/integration/api/v1/contents/[username]/[slug]/get.test.js b/tests/integration/api/v1/contents/[username]/[slug]/get.test.js
index 7cadef0f4..768d8b772 100644
--- a/tests/integration/api/v1/contents/[username]/[slug]/get.test.js
+++ b/tests/integration/api/v1/contents/[username]/[slug]/get.test.js
@@ -96,6 +96,7 @@ describe('GET /api/v1/contents/[username]/[slug]', () => {
title: 'Conteúdo publicamente disponível',
body: 'Conteúdo relevante deveria estar disponível para todos.',
status: 'published',
+ type: 'content',
tabcoins: 1,
tabcoins_credit: 0,
tabcoins_debit: 0,
@@ -203,6 +204,7 @@ describe('GET /api/v1/contents/[username]/[slug]', () => {
title: 'Conteúdo root',
body: 'Body with relevant texts needs to contain a good amount of words',
status: 'published',
+ type: 'content',
tabcoins: 1,
tabcoins_credit: 0,
tabcoins_debit: 0,
@@ -285,6 +287,7 @@ describe('GET /api/v1/contents/[username]/[slug]', () => {
title: null,
body: 'Conteúdo child',
status: 'published',
+ type: 'content',
tabcoins: 0,
tabcoins_credit: 0,
tabcoins_debit: 0,
@@ -355,6 +358,7 @@ describe('GET /api/v1/contents/[username]/[slug]', () => {
title: null,
body: 'Conteúdo child',
status: 'published',
+ type: 'content',
tabcoins: 0,
tabcoins_credit: 0,
tabcoins_debit: 0,
@@ -441,6 +445,7 @@ describe('GET /api/v1/contents/[username]/[slug]', () => {
title: 'Conteúdo com TabCoins',
body: 'Conteúdo que foi avaliado positiva e negativamente.',
status: 'published',
+ type: 'content',
tabcoins: 2,
tabcoins_credit: 3,
tabcoins_debit: -1,
diff --git a/tests/integration/api/v1/contents/[username]/[slug]/parent/get.test.js b/tests/integration/api/v1/contents/[username]/[slug]/parent/get.test.js
index c3492d030..8f6f33ef7 100644
--- a/tests/integration/api/v1/contents/[username]/[slug]/parent/get.test.js
+++ b/tests/integration/api/v1/contents/[username]/[slug]/parent/get.test.js
@@ -224,6 +224,7 @@ describe('GET /api/v1/contents/[username]/[slug]/parent', () => {
body: 'Root - Body with relevant texts needs to contain a good amount of words',
children_deep_count: 1,
status: 'published',
+ type: 'content',
source_url: null,
published_at: rootContent.published_at.toISOString(),
created_at: rootContent.created_at.toISOString(),
@@ -287,6 +288,7 @@ describe('GET /api/v1/contents/[username]/[slug]/parent', () => {
body: 'Child content body Level 2 - relevant content',
children_deep_count: 1,
status: 'published',
+ type: 'content',
source_url: null,
published_at: childContentLevel2.published_at.toISOString(),
created_at: childContentLevel2.created_at.toISOString(),
@@ -354,6 +356,7 @@ describe('GET /api/v1/contents/[username]/[slug]/parent', () => {
body: '[Não disponível]',
children_deep_count: 0,
status: 'draft',
+ type: 'content',
source_url: null,
published_at: null,
created_at: childContentLevel2.created_at.toISOString(),
@@ -422,6 +425,7 @@ describe('GET /api/v1/contents/[username]/[slug]/parent', () => {
body: '[Não disponível]',
children_deep_count: 0,
status: 'deleted',
+ type: 'content',
source_url: null,
published_at: childContentLevel2.published_at.toISOString(),
created_at: childContentLevel2.created_at.toISOString(),
@@ -472,6 +476,7 @@ describe('GET /api/v1/contents/[username]/[slug]/parent', () => {
body: 'Root - Body with relevant texts needs to contain a good amount of words',
children_deep_count: 1,
status: 'published',
+ type: 'content',
source_url: null,
published_at: rootContent.published_at.toISOString(),
created_at: rootContent.created_at.toISOString(),
diff --git a/tests/integration/api/v1/contents/[username]/[slug]/patch.test.js b/tests/integration/api/v1/contents/[username]/[slug]/patch.test.js
index 0a379bf66..fa5a5619e 100644
--- a/tests/integration/api/v1/contents/[username]/[slug]/patch.test.js
+++ b/tests/integration/api/v1/contents/[username]/[slug]/patch.test.js
@@ -152,6 +152,7 @@ describe('PATCH /api/v1/contents/[username]/[slug]', () => {
title: null,
body: 'Updated body, even without "create:content:text_root" feature.',
status: 'published',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -198,6 +199,7 @@ describe('PATCH /api/v1/contents/[username]/[slug]', () => {
title: 'Valid user trying to update "root" content.',
body: 'It should be possible, even without the "create:content:text_child" feature.',
status: 'published',
+ type: 'content',
source_url: 'http://www.tabnews.com.br/',
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -453,6 +455,7 @@ describe('PATCH /api/v1/contents/[username]/[slug]', () => {
title: 'Tentando atualizar o dono do conteúdo.',
body: 'Campo "owner_id" da request deveria ser ignorado e pego através da sessão.',
status: 'published',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -496,6 +499,7 @@ describe('PATCH /api/v1/contents/[username]/[slug]', () => {
title: 'Título velho',
body: 'Body novo',
status: 'draft',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -541,6 +545,7 @@ describe('PATCH /api/v1/contents/[username]/[slug]', () => {
title: 'Title',
body: 'New body',
status: 'draft',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -641,6 +646,7 @@ describe('PATCH /api/v1/contents/[username]/[slug]', () => {
title: 'Começando com caractere proibido no Postgres',
body: 'Terminando com caractere proibido no Postgres',
status: 'draft',
+ type: 'content',
source_url: 'https://teste-caractere.invalido/',
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -760,6 +766,7 @@ describe('PATCH /api/v1/contents/[username]/[slug]', () => {
title: 'Título velho',
body: 'Espaço só no fim',
status: 'draft',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -828,6 +835,7 @@ describe('PATCH /api/v1/contents/[username]/[slug]', () => {
title: 'Título velho',
body: 'Body velho',
status: 'draft',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -968,6 +976,7 @@ describe('PATCH /api/v1/contents/[username]/[slug]', () => {
title: 'Segundo conteúdo',
body: 'Segundo conteúdo',
status: 'published',
+ type: 'content',
tabcoins: 0,
tabcoins_credit: 0,
tabcoins_debit: 0,
@@ -1042,6 +1051,7 @@ describe('PATCH /api/v1/contents/[username]/[slug]', () => {
title: 'Título velho',
body: 'Body velho',
status: 'draft',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -1136,6 +1146,7 @@ describe('PATCH /api/v1/contents/[username]/[slug]', () => {
title: 'Título velho',
body: 'Body velho',
status: 'draft',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -1178,6 +1189,7 @@ describe('PATCH /api/v1/contents/[username]/[slug]', () => {
title: 'Título novo',
body: 'Body velho',
status: 'draft',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -1339,6 +1351,7 @@ describe('PATCH /api/v1/contents/[username]/[slug]', () => {
title: null,
body: 'Child old body',
status: 'draft',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -1381,6 +1394,7 @@ describe('PATCH /api/v1/contents/[username]/[slug]', () => {
title: 'Título válido, mas com espaços em branco no início e no fim',
body: 'Body velho',
status: 'draft',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -1423,6 +1437,7 @@ describe('PATCH /api/v1/contents/[username]/[slug]', () => {
title: `Tab & News | Conteúdos com \n valor concreto e "massa"> participe! '\\o/'`,
body: 'Body velho',
status: 'draft',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -1465,6 +1480,7 @@ describe('PATCH /api/v1/contents/[username]/[slug]', () => {
title: 'Título velho',
body: 'Body velho',
status: 'draft',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -1508,6 +1524,7 @@ describe('PATCH /api/v1/contents/[username]/[slug]', () => {
title: 'Título velho',
body: 'Body with relevant texts needs to contain a good amount of words',
status: 'published',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -1584,6 +1601,7 @@ describe('PATCH /api/v1/contents/[username]/[slug]', () => {
title: 'Title',
body: 'Body with relevant texts needs to contain a good amount of words',
status: 'deleted',
+ type: 'content',
tabcoins: 1,
tabcoins_credit: 0,
tabcoins_debit: 0,
@@ -1775,6 +1793,7 @@ describe('PATCH /api/v1/contents/[username]/[slug]', () => {
title: 'Título velho',
body: 'Body velho',
status: 'draft',
+ type: 'content',
source_url: 'http://www.tabnews.com.br/',
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -1817,6 +1836,7 @@ describe('PATCH /api/v1/contents/[username]/[slug]', () => {
title: 'Título velho',
body: 'Body velho',
status: 'draft',
+ type: 'content',
source_url: 'https://www.tabnews.com.br/museu',
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -1859,6 +1879,7 @@ describe('PATCH /api/v1/contents/[username]/[slug]', () => {
title: 'Alterar um baita de um Top-Level Domain',
body: 'O maior TLD listado em http://data.iana.org/TLD/tlds-alpha-by-domain.txt possuía 24 caracteres',
status: 'draft',
+ type: 'content',
source_url: 'https://nic.xn--vermgensberatung-pwb/',
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -1901,6 +1922,7 @@ describe('PATCH /api/v1/contents/[username]/[slug]', () => {
title: 'Alterar URL bem curta',
body: 'Por exemplo o encurtador do Telegram',
status: 'draft',
+ type: 'content',
source_url: 'https://t.me',
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -2078,6 +2100,7 @@ describe('PATCH /api/v1/contents/[username]/[slug]', () => {
title: 'Título velho',
body: 'Body velho',
status: 'draft',
+ type: 'content',
source_url: 'https://www.tabnews.com.br/api/v1/contents?strategy=old',
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -2121,6 +2144,7 @@ describe('PATCH /api/v1/contents/[username]/[slug]', () => {
title: 'Título velho',
body: 'Body velho',
status: 'draft',
+ type: 'content',
source_url: 'https://www.tabnews.com.br/#:~:text=TabNews,-Status',
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -2190,6 +2214,7 @@ describe('PATCH /api/v1/contents/[username]/[slug]', () => {
title: 'Título velho',
body: 'Body velho',
status: 'draft',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -2281,6 +2306,7 @@ describe('PATCH /api/v1/contents/[username]/[slug]', () => {
title: 'Updated title, but not "parent_id"',
body: 'Child content body',
status: 'draft',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -3176,6 +3202,7 @@ describe('PATCH /api/v1/contents/[username]/[slug]', () => {
title: 'Novo title.',
body: 'Novo body.',
status: 'published',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
diff --git a/tests/integration/api/v1/contents/[username]/[slug]/root/get.test.js b/tests/integration/api/v1/contents/[username]/[slug]/root/get.test.js
index 10aa3c700..12a828e41 100644
--- a/tests/integration/api/v1/contents/[username]/[slug]/root/get.test.js
+++ b/tests/integration/api/v1/contents/[username]/[slug]/root/get.test.js
@@ -224,6 +224,7 @@ describe('GET /api/v1/contents/[username]/[slug]/root', () => {
body: 'Body with relevant texts needs to contain a good amount of words',
children_deep_count: 1,
status: 'published',
+ type: 'content',
source_url: null,
published_at: rootContent.published_at.toISOString(),
created_at: rootContent.created_at.toISOString(),
@@ -287,6 +288,7 @@ describe('GET /api/v1/contents/[username]/[slug]/root', () => {
body: 'Body with relevant texts needs to contain a good amount of words',
children_deep_count: 3,
status: 'published',
+ type: 'content',
source_url: null,
published_at: rootContent.published_at.toISOString(),
created_at: rootContent.created_at.toISOString(),
@@ -355,6 +357,7 @@ describe('GET /api/v1/contents/[username]/[slug]/root', () => {
body: 'Body with relevant texts needs to contain a good amount of words',
children_deep_count: 2,
status: 'published',
+ type: 'content',
source_url: null,
published_at: rootContent.published_at.toISOString(),
created_at: rootContent.created_at.toISOString(),
@@ -422,6 +425,7 @@ describe('GET /api/v1/contents/[username]/[slug]/root', () => {
title: '[Não disponível]',
body: '[Não disponível]',
status: 'draft',
+ type: 'content',
source_url: null,
published_at: null,
created_at: rootContent.created_at.toISOString(),
@@ -491,6 +495,7 @@ describe('GET /api/v1/contents/[username]/[slug]/root', () => {
title: '[Não disponível]',
body: '[Não disponível]',
status: 'deleted',
+ type: 'content',
source_url: null,
published_at: rootContent.published_at.toISOString(),
created_at: rootContent.created_at.toISOString(),
@@ -550,6 +555,7 @@ describe('GET /api/v1/contents/[username]/[slug]/root', () => {
body: 'Body with relevant texts needs to contain a good amount of words',
children_deep_count: 2,
status: 'published',
+ type: 'content',
source_url: null,
published_at: rootContent.published_at.toISOString(),
created_at: rootContent.created_at.toISOString(),
diff --git a/tests/integration/api/v1/contents/[username]/get.test.js b/tests/integration/api/v1/contents/[username]/get.test.js
index e4c0cf9be..ffb151b11 100644
--- a/tests/integration/api/v1/contents/[username]/get.test.js
+++ b/tests/integration/api/v1/contents/[username]/get.test.js
@@ -115,6 +115,7 @@ describe('GET /api/v1/contents/[username]', () => {
title: null,
body: 'Child content',
status: 'published',
+ type: 'content',
source_url: null,
created_at: childContent.created_at.toISOString(),
updated_at: childContent.updated_at.toISOString(),
@@ -174,6 +175,7 @@ describe('GET /api/v1/contents/[username]', () => {
title: null,
body: 'Diferente do teste anterior, o corpo dessa publicação é grande, com quebras de linha, Markdown e ultrapassa o limite de caracteres que iremos devolver pelo response. Motivo Hoje estamos usando o mesmo número de caracteres de um title para que o fronten...',
status: 'published',
+ type: 'content',
source_url: null,
created_at: childContent.created_at.toISOString(),
updated_at: childContent.updated_at.toISOString(),
@@ -242,6 +244,7 @@ describe('GET /api/v1/contents/[username]', () => {
title: null,
body: 'Este conteúdo agora deverá aparecer na lista retornada pelo /contents/[username]',
status: 'published',
+ type: 'content',
source_url: null,
created_at: childContent.created_at.toISOString(),
updated_at: childContent.updated_at.toISOString(),
@@ -260,6 +263,7 @@ describe('GET /api/v1/contents/[username]', () => {
slug: 'segundo-conteudo-criado',
title: 'Segundo conteúdo criado',
status: 'published',
+ type: 'content',
source_url: null,
created_at: secondRootContent.created_at.toISOString(),
updated_at: secondRootContent.updated_at.toISOString(),
@@ -278,6 +282,7 @@ describe('GET /api/v1/contents/[username]', () => {
slug: 'primeiro-conteudo-criado',
title: 'Primeiro conteúdo criado',
status: 'published',
+ type: 'content',
source_url: null,
created_at: firstRootContent.created_at.toISOString(),
updated_at: firstRootContent.updated_at.toISOString(),
@@ -353,6 +358,7 @@ describe('GET /api/v1/contents/[username]', () => {
title: 'Quarto conteúdo criado',
body: 'Este conteúdo que agora deverá aparecer na lista retornada pelo /contents/[username]',
status: 'published',
+ type: 'content',
source_url: null,
created_at: childContent.created_at.toISOString(),
updated_at: childContent.updated_at.toISOString(),
@@ -371,6 +377,7 @@ describe('GET /api/v1/contents/[username]', () => {
slug: 'segundo-conteudo-criado',
title: 'Segundo conteúdo criado',
status: 'published',
+ type: 'content',
source_url: null,
created_at: secondRootContent.created_at.toISOString(),
updated_at: secondRootContent.updated_at.toISOString(),
@@ -389,6 +396,7 @@ describe('GET /api/v1/contents/[username]', () => {
slug: 'primeiro-conteudo-criado',
title: 'Primeiro conteúdo criado',
status: 'published',
+ type: 'content',
source_url: null,
created_at: firstRootContent.created_at.toISOString(),
updated_at: firstRootContent.updated_at.toISOString(),
@@ -446,6 +454,7 @@ describe('GET /api/v1/contents/[username]', () => {
title: 'Comentário',
body: 'Um comentário',
status: 'published',
+ type: 'content',
source_url: null,
created_at: childContent.created_at.toISOString(),
updated_at: childContent.updated_at.toISOString(),
@@ -464,6 +473,7 @@ describe('GET /api/v1/contents/[username]', () => {
slug: 'conteudo-raiz',
title: 'Conteúdo raiz',
status: 'published',
+ type: 'content',
source_url: null,
created_at: rootContent.created_at.toISOString(),
updated_at: rootContent.updated_at.toISOString(),
@@ -823,6 +833,7 @@ describe('GET /api/v1/contents/[username]', () => {
slug: 'segundo-conteudo-criado',
title: 'Segundo conteúdo criado',
status: 'published',
+ type: 'content',
source_url: null,
created_at: secondRootContent.created_at.toISOString(),
updated_at: secondRootContent.updated_at.toISOString(),
@@ -841,6 +852,7 @@ describe('GET /api/v1/contents/[username]', () => {
slug: 'primeiro-conteudo-criado',
title: 'Primeiro conteúdo criado',
status: 'published',
+ type: 'content',
source_url: null,
created_at: firstRootContent.created_at.toISOString(),
updated_at: firstRootContent.updated_at.toISOString(),
@@ -936,6 +948,7 @@ describe('GET /api/v1/contents/[username]', () => {
title: 'Quinto conteúdo criado',
body: 'Este conteúdo deverá aparecer na lista retornada pelo /contents/[username]',
status: 'published',
+ type: 'content',
source_url: null,
created_at: secondChildContent.created_at.toISOString(),
updated_at: secondChildContent.updated_at.toISOString(),
@@ -955,6 +968,7 @@ describe('GET /api/v1/contents/[username]', () => {
title: 'Quarto conteúdo criado',
body: 'Este conteúdo deverá aparecer na lista retornada pelo /contents/[username]',
status: 'published',
+ type: 'content',
source_url: null,
created_at: firstChildContent.created_at.toISOString(),
updated_at: firstChildContent.updated_at.toISOString(),
diff --git a/tests/integration/api/v1/contents/get.test.js b/tests/integration/api/v1/contents/get.test.js
index efab97a9e..681dc4468 100644
--- a/tests/integration/api/v1/contents/get.test.js
+++ b/tests/integration/api/v1/contents/get.test.js
@@ -149,6 +149,7 @@ describe('GET /api/v1/contents', () => {
slug: 'segundo-conteudo-criado',
title: 'Segundo conteúdo criado',
status: 'published',
+ type: 'content',
source_url: null,
created_at: secondRootContent.created_at.toISOString(),
updated_at: secondRootContent.updated_at.toISOString(),
@@ -167,6 +168,7 @@ describe('GET /api/v1/contents', () => {
slug: 'primeiro-conteudo-criado',
title: 'Primeiro conteúdo criado',
status: 'published',
+ type: 'content',
source_url: null,
created_at: firstRootContent.created_at.toISOString(),
updated_at: firstRootContent.updated_at.toISOString(),
@@ -245,6 +247,7 @@ describe('GET /api/v1/contents', () => {
slug: 'primeiro-conteudo-criado',
title: 'Primeiro conteúdo criado',
status: 'published',
+ type: 'content',
source_url: null,
created_at: firstRootContent.created_at.toISOString(),
updated_at: firstRootContent.updated_at.toISOString(),
@@ -263,6 +266,7 @@ describe('GET /api/v1/contents', () => {
slug: 'segundo-conteudo-criado',
title: 'Segundo conteúdo criado',
status: 'published',
+ type: 'content',
source_url: null,
created_at: secondRootContent.created_at.toISOString(),
updated_at: secondRootContent.updated_at.toISOString(),
@@ -334,6 +338,7 @@ describe('GET /api/v1/contents', () => {
slug: 'conteudo-raiz',
title: 'Conteúdo raiz',
status: 'published',
+ type: 'content',
source_url: null,
created_at: rootContent.created_at.toISOString(),
updated_at: rootContent.updated_at.toISOString(),
@@ -1278,6 +1283,7 @@ describe('GET /api/v1/contents', () => {
slug: 'primeiro-conteudo-criado',
title: 'Primeiro conteúdo criado',
status: 'published',
+ type: 'content',
source_url: null,
created_at: firstRootContent.created_at.toISOString(),
updated_at: firstRootContent.updated_at.toISOString(),
@@ -1304,6 +1310,7 @@ describe('GET /api/v1/contents', () => {
slug: 'segundo-conteudo-criado',
title: 'Segundo conteúdo criado',
status: 'published',
+ type: 'content',
source_url: null,
created_at: secondRootContent.created_at.toISOString(),
updated_at: secondRootContent.updated_at.toISOString(),
@@ -1329,6 +1336,7 @@ describe('GET /api/v1/contents', () => {
title: null,
body: comment.body,
status: 'published',
+ type: 'content',
source_url: null,
created_at: comment.created_at.toISOString(),
updated_at: comment.updated_at.toISOString(),
diff --git a/tests/integration/api/v1/contents/post.test.js b/tests/integration/api/v1/contents/post.test.js
index 78fdae1b1..e5a20cb43 100644
--- a/tests/integration/api/v1/contents/post.test.js
+++ b/tests/integration/api/v1/contents/post.test.js
@@ -1,7 +1,6 @@
import { version as uuidVersion } from 'uuid';
import database from 'infra/database';
-import content from 'models/content';
import { defaultTabCashForAdCreation, maxSlugLength, maxTitleLength } from 'tests/constants-for-tests';
import orchestrator from 'tests/orchestrator.js';
import RequestBuilder from 'tests/request-builder';
@@ -152,6 +151,7 @@ describe('POST /api/v1/contents', () => {
title: 'Tentando criar conteúdo em nome de outro usuário',
body: 'Campo "owner_id" da request deveria ser ignorado e pego através da sessão.',
status: 'draft',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -299,6 +299,7 @@ describe('POST /api/v1/contents', () => {
title: 'Começando com caractere proibido no Postgres',
body: 'Terminando com caractere proibido no Postgres',
status: 'draft',
+ type: 'content',
source_url: 'https://teste-caractere.invalido/',
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -391,6 +392,7 @@ describe('POST /api/v1/contents', () => {
title: 'Título normal',
body: 'Espaço só no fim',
status: 'draft',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -446,6 +448,7 @@ describe('POST /api/v1/contents', () => {
title: 'Mini curso de Node.js',
body: 'Instale o Node.js',
status: 'draft',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -508,6 +511,7 @@ describe('POST /api/v1/contents', () => {
title: 'Mini curso de Node.js',
body: 'Instale o Node.js',
status: 'draft',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -664,6 +668,7 @@ describe('POST /api/v1/contents', () => {
title: 'Conteúdo existente',
body: 'Outro body',
status: 'published',
+ type: 'content',
tabcoins: 0,
tabcoins_credit: 0,
tabcoins_debit: 0,
@@ -700,6 +705,7 @@ describe('POST /api/v1/contents', () => {
title: 'Mini curso de Node.js',
body: 'Instale o Node.js',
status: 'draft',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -784,6 +790,7 @@ describe('POST /api/v1/contents', () => {
),
body: 'Instale o Node.js',
status: 'draft',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -819,6 +826,7 @@ describe('POST /api/v1/contents', () => {
title: 'Braille Pattern Blank Unicode Character',
body: 'Instale o Node.js',
status: 'draft',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -854,6 +862,7 @@ describe('POST /api/v1/contents', () => {
title: '♥'.repeat(maxTitleLength),
body: `The title is ${maxTitleLength} characters but 765 bytes and the slug should only be ${maxSlugLength} bytes`,
status: 'draft',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -889,6 +898,7 @@ describe('POST /api/v1/contents', () => {
title: 'Título válido, mas com espaços em branco no início e no fim',
body: 'Qualquer coisa.',
status: 'draft',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -924,6 +934,7 @@ describe('POST /api/v1/contents', () => {
title: `Tab & News | Conteúdos com \n valor concreto e "massa"> participe! '\\o/'`,
body: 'Qualquer coisa.',
status: 'draft',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -960,6 +971,7 @@ describe('POST /api/v1/contents', () => {
title: 'Deveria criar um conteúdo com status "draft".',
body: 'Qualquer coisa.',
status: 'draft',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -996,6 +1008,7 @@ describe('POST /api/v1/contents', () => {
title: 'Deveria criar um conteúdo com status "published".',
body: 'E isso vai fazer ter um "published_at" preenchido automaticamente.',
status: 'published',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -1147,6 +1160,7 @@ describe('POST /api/v1/contents', () => {
title: 'TabNews',
body: 'Somos pessoas brutalmente exatas e empáticas, simultaneamente.',
status: 'draft',
+ type: 'content',
source_url: 'http://www.tabnews.com.br/',
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -1183,6 +1197,7 @@ describe('POST /api/v1/contents', () => {
title: 'TabNews: Onde Tudo Começou',
body: 'Aqui você vai encontrar POCs que foram criadas pela turma no início do projeto.',
status: 'draft',
+ type: 'content',
source_url: 'https://www.tabnews.com.br/museu',
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -1219,6 +1234,7 @@ describe('POST /api/v1/contents', () => {
title: 'Um baita de um Top-Level Domain',
body: 'O maior TLD listado em http://data.iana.org/TLD/tlds-alpha-by-domain.txt possuía 24 caracteres',
status: 'draft',
+ type: 'content',
source_url: 'http://nic.xn--vermgensberatung-pwb/',
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -1255,6 +1271,7 @@ describe('POST /api/v1/contents', () => {
title: 'URL bem curta',
body: 'Por exemplo o encurtador do Telegram',
status: 'draft',
+ type: 'content',
source_url: 'https://t.me',
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -1401,6 +1418,7 @@ describe('POST /api/v1/contents', () => {
title: 'Titulo',
body: 'Corpo',
status: 'draft',
+ type: 'content',
source_url: 'https://www.tabnews.com.br/api/v1/contents?strategy=old',
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -1437,6 +1455,7 @@ describe('POST /api/v1/contents', () => {
title: 'Titulo',
body: 'Corpo',
status: 'draft',
+ type: 'content',
source_url: 'http://www.tabnews.com.br/#:~:text=TabNews,-Status',
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -1493,6 +1512,7 @@ describe('POST /api/v1/contents', () => {
title: 'Titulo',
body: 'Corpo',
status: 'draft',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -1530,6 +1550,7 @@ describe('POST /api/v1/contents', () => {
'Deveria conseguir! E o campo "slug" é opcional & 95,5% dos usuários não usam :) [áéíóú?@#$*<>|+-=.,;:_] <- (caracteres especiais)',
body: 'Deveria conseguir, pois atualmente todos os usuários recebem todas as features relacionadas a "content".',
status: 'draft',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -1572,6 +1593,7 @@ describe('POST /api/v1/contents', () => {
title: 'under_score 5% é >= 1 e <= 10 email@dominio.com #item1,item2 a&b | a & b/mil',
body: 'Body',
status: 'draft',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -1650,6 +1672,7 @@ describe('POST /api/v1/contents', () => {
title: null,
body: 'Deveria conseguir, pois atualmente todos os usuários recebem todas as features relacionadas a "content".',
status: 'draft',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -1701,6 +1724,7 @@ describe('POST /api/v1/contents', () => {
title: null,
body: 'Deveria criar um slug com UUID V4',
status: 'published',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -1746,6 +1770,7 @@ describe('POST /api/v1/contents', () => {
title: 'Título em um child content! O que vai acontecer?',
body: 'Deveria criar um slug baseado no "title"',
status: 'published',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -2422,6 +2447,7 @@ describe('POST /api/v1/contents', () => {
title: 'Title',
body: 'Body with relevant texts needs to contain a good amount of words',
status: 'published',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -2473,6 +2499,7 @@ describe('POST /api/v1/contents', () => {
title: null,
body: 'Deveria conseguir mesmo com alguns comentários mal avaliados.',
status: 'published',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -2516,6 +2543,7 @@ describe('POST /api/v1/contents', () => {
title: 'Title',
body: 'Body with relevant texts needs to contain a good amount of words',
status: 'published',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -2567,6 +2595,7 @@ describe('POST /api/v1/contents', () => {
title: null,
body: 'Deve conseguir publicar, mas não deve ganhar TabCoins sem prestígio suficiente.',
status: 'published',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -2610,6 +2639,7 @@ describe('POST /api/v1/contents', () => {
title: 'Title',
body: 'Body with relevant texts needs to contain a good amount of words',
status: 'published',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -2661,6 +2691,7 @@ describe('POST /api/v1/contents', () => {
title: null,
body: 'Deve conseguir publicar e ganhar TabCoins com esse texto.',
status: 'published',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -2733,6 +2764,7 @@ describe('POST /api/v1/contents', () => {
title: 'Title',
body: 'Body with no minimum amount of relevant words',
status: 'published',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -2784,6 +2816,7 @@ describe('POST /api/v1/contents', () => {
title: null,
body: 'Body with no minimum amount of relevant words',
status: 'published',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -2829,6 +2862,7 @@ describe('POST /api/v1/contents', () => {
title: 'Title',
body: 'Relevant text needs to contain a good amount of words',
status: 'published',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -2880,6 +2914,7 @@ describe('POST /api/v1/contents', () => {
title: null,
body: 'Relevant text needs to contain a good amount of words',
status: 'published',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -2921,9 +2956,6 @@ describe('POST /api/v1/contents', () => {
source_url: 'https://www.tabnews.com.br',
});
- const createdAdContent = await content.findOne({ where: { id: responseBody.id } });
-
- expect.soft(createdAdContent.type).toBe('ad');
expect.soft(response.status).toBe(201);
expect(responseBody).toStrictEqual({
@@ -2934,6 +2966,7 @@ describe('POST /api/v1/contents', () => {
title: 'Ad title',
body: 'Ad body',
status: 'published',
+ type: 'ad',
source_url: 'https://www.tabnews.com.br',
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,
@@ -3033,9 +3066,6 @@ describe('POST /api/v1/contents', () => {
parent_id: rootContent.id,
});
- const createdAdContent = await content.findOne({ where: { id: responseBody.id } });
-
- expect.soft(createdAdContent.type).toBe('content');
expect.soft(response.status).toBe(201);
expect(responseBody).toStrictEqual({
@@ -3046,6 +3076,7 @@ describe('POST /api/v1/contents', () => {
title: 'Ad title',
body: 'Ad body',
status: 'published',
+ type: 'content',
source_url: null,
created_at: responseBody.created_at,
updated_at: responseBody.updated_at,