mirror of
https://github.com/IT4Change/Ocelot-Social.git
synced 2025-12-13 07:45:56 +00:00
test(cypress): Cover "Pinned post" feature
* Implement cypress tests
- Start implementation of cypress tests for pinned posts
* Test that Admin can pin a post
- Tests the process of an admin pinning a post
* Resolve failing tests
- Fix ordering of posts immediately after pinning posts by reloading page
- Check that tests are pinned posts are displayed first for role user
* Refactor to seperate the initialization
- Of the post data created in the database during setup
* Fix toaster test
* test(cypress): Add missing parts for pin feature
* docs(cucumber): Link to admin 🥒 folder
* Follow @mattwr18's suggestions
* test(backend): Order pinned posts like frontend
@mattwr18 I think this was a false negative.
Co-authored-by: Robert Schäfer <git@roschaefer.de>
This commit is contained in:
parent
42c08d4296
commit
d49afc25cf
@ -41,4 +41,6 @@ export default {
|
|||||||
language: { type: 'string', allow: [null] },
|
language: { type: 'string', allow: [null] },
|
||||||
imageBlurred: { type: 'boolean', default: false },
|
imageBlurred: { type: 'boolean', default: false },
|
||||||
imageAspectRatio: { type: 'float', default: 1.0 },
|
imageAspectRatio: { type: 'float', default: 1.0 },
|
||||||
|
pinned: { type: 'boolean', default: null, valid: [null, true] },
|
||||||
|
pinnedAt: { type: 'string', isoDate: true },
|
||||||
}
|
}
|
||||||
|
|||||||
@ -682,24 +682,23 @@ describe('UpdatePost', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('PostOrdering', () => {
|
describe('PostOrdering', () => {
|
||||||
let pinnedPost, admin
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
;[pinnedPost] = await Promise.all([
|
await factory.create('Post', {
|
||||||
neode.create('Post', {
|
|
||||||
id: 'im-a-pinned-post',
|
id: 'im-a-pinned-post',
|
||||||
|
createdAt: '2019-11-22T17:26:29.070Z',
|
||||||
pinned: true,
|
pinned: true,
|
||||||
}),
|
|
||||||
neode.create('Post', {
|
|
||||||
id: 'i-was-created-after-pinned-post',
|
|
||||||
createdAt: '2019-10-22T17:26:29.070Z', // this should always be 3rd
|
|
||||||
}),
|
|
||||||
])
|
|
||||||
admin = await user.update({
|
|
||||||
role: 'admin',
|
|
||||||
name: 'Admin',
|
|
||||||
updatedAt: new Date().toISOString(),
|
|
||||||
})
|
})
|
||||||
await admin.relateTo(pinnedPost, 'pinned')
|
await factory.create('Post', {
|
||||||
|
id: 'i-was-created-before-pinned-post',
|
||||||
|
// fairly old, so this should be 3rd
|
||||||
|
createdAt: '2019-10-22T17:26:29.070Z',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('order by `pinned_asc` and `createdAt_desc`', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
// this is the ordering in the frontend
|
||||||
|
variables = { orderBy: ['pinned_asc', 'createdAt_desc'] }
|
||||||
})
|
})
|
||||||
|
|
||||||
it('pinned post appear first even when created before other posts', async () => {
|
it('pinned post appear first even when created before other posts', async () => {
|
||||||
@ -707,33 +706,38 @@ describe('UpdatePost', () => {
|
|||||||
query($orderBy: [_PostOrdering]) {
|
query($orderBy: [_PostOrdering]) {
|
||||||
Post(orderBy: $orderBy) {
|
Post(orderBy: $orderBy) {
|
||||||
id
|
id
|
||||||
|
pinned
|
||||||
|
createdAt
|
||||||
pinnedAt
|
pinnedAt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
const expected = {
|
await expect(query({ query: postOrderingQuery, variables })).resolves.toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
Post: [
|
Post: [
|
||||||
{
|
{
|
||||||
id: 'im-a-pinned-post',
|
id: 'im-a-pinned-post',
|
||||||
|
pinned: true,
|
||||||
|
createdAt: '2019-11-22T17:26:29.070Z',
|
||||||
pinnedAt: expect.any(String),
|
pinnedAt: expect.any(String),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'p9876',
|
id: 'p9876',
|
||||||
|
pinned: null,
|
||||||
|
createdAt: expect.any(String),
|
||||||
pinnedAt: null,
|
pinnedAt: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'i-was-created-after-pinned-post',
|
id: 'i-was-created-before-pinned-post',
|
||||||
|
pinned: null,
|
||||||
|
createdAt: '2019-10-22T17:26:29.070Z',
|
||||||
pinnedAt: null,
|
pinnedAt: null,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
errors: undefined,
|
errors: undefined,
|
||||||
}
|
})
|
||||||
variables = { orderBy: ['pinned_desc', 'createdAt_desc'] }
|
})
|
||||||
await expect(query({ query: postOrderingQuery, variables })).resolves.toMatchObject(
|
|
||||||
expected,
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -21,11 +21,15 @@ export default function create() {
|
|||||||
categoryIds: [],
|
categoryIds: [],
|
||||||
imageBlurred: false,
|
imageBlurred: false,
|
||||||
imageAspectRatio: 1.333,
|
imageAspectRatio: 1.333,
|
||||||
|
pinned: null,
|
||||||
}
|
}
|
||||||
args = {
|
args = {
|
||||||
...defaults,
|
...defaults,
|
||||||
...args,
|
...args,
|
||||||
}
|
}
|
||||||
|
// Convert false to null
|
||||||
|
args.pinned = args.pinned || null
|
||||||
|
|
||||||
args.slug = args.slug || slugify(args.title, { lower: true })
|
args.slug = args.slug || slugify(args.title, { lower: true })
|
||||||
args.contentExcerpt = args.contentExcerpt || args.content
|
args.contentExcerpt = args.contentExcerpt || args.content
|
||||||
|
|
||||||
@ -50,9 +54,21 @@ export default function create() {
|
|||||||
if (author && authorId) throw new Error('You provided both author and authorId')
|
if (author && authorId) throw new Error('You provided both author and authorId')
|
||||||
if (authorId) author = await neodeInstance.find('User', authorId)
|
if (authorId) author = await neodeInstance.find('User', authorId)
|
||||||
author = author || (await factoryInstance.create('User'))
|
author = author || (await factoryInstance.create('User'))
|
||||||
|
|
||||||
const post = await neodeInstance.create('Post', args)
|
const post = await neodeInstance.create('Post', args)
|
||||||
await post.relateTo(author, 'author')
|
await post.relateTo(author, 'author')
|
||||||
|
|
||||||
|
if (args.pinned) {
|
||||||
|
args.pinnedAt = args.pinnedAt || new Date().toISOString()
|
||||||
|
if (!args.pinnedBy) {
|
||||||
|
const admin = await factoryInstance.create('User', {
|
||||||
|
role: 'admin',
|
||||||
|
updatedAt: new Date().toISOString(),
|
||||||
|
})
|
||||||
|
await admin.relateTo(post, 'pinned')
|
||||||
|
args.pinnedBy = admin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(categories.map(c => c.relateTo(post, 'post')))
|
await Promise.all(categories.map(c => c.relateTo(post, 'post')))
|
||||||
await Promise.all(tags.map(t => t.relateTo(post, 'post')))
|
await Promise.all(tags.map(t => t.relateTo(post, 'post')))
|
||||||
return post
|
return post
|
||||||
|
|||||||
@ -249,10 +249,12 @@ Shows automatically related actions for existing post.
|
|||||||
|
|
||||||
### Administration
|
### Administration
|
||||||
|
|
||||||
|
[Cucumber Features](https://github.com/Human-Connection/Human-Connection/tree/master/cypress/integration/administration)
|
||||||
|
|
||||||
* Provide Admin-Interface to send Users Invite Code
|
* Provide Admin-Interface to send Users Invite Code
|
||||||
* Static Pages for Data Privacy Statement ...
|
* Static Pages for Data Privacy Statement ...
|
||||||
* Create, edit and delete Announcements
|
* Create, edit and delete Announcements
|
||||||
* Show Announcements on top of User Interface
|
* Pin a post to inform users
|
||||||
|
|
||||||
### Invitation
|
### Invitation
|
||||||
|
|
||||||
|
|||||||
36
cypress/integration/administration/PinPost.feature
Normal file
36
cypress/integration/administration/PinPost.feature
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
Feature: Pin a post
|
||||||
|
As an admin
|
||||||
|
I want to pin a post so that it always appears at the top
|
||||||
|
In order to make sure all network users read it - e.g. notify people about security incidents, maintenance downtimes
|
||||||
|
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given we have the following posts in our database:
|
||||||
|
| id | title | pinned | createdAt |
|
||||||
|
| p1 | Some other post | | 2020-01-21 |
|
||||||
|
| p2 | Houston we have a problem | x | 2020-01-20 |
|
||||||
|
| p3 | Yet another post | | 2020-01-19 |
|
||||||
|
|
||||||
|
Scenario: Pinned post always appears on the top of the newsfeed
|
||||||
|
Given I am logged in with a "user" role
|
||||||
|
Then the first post on the landing page has the title:
|
||||||
|
"""
|
||||||
|
Houston we have a problem
|
||||||
|
"""
|
||||||
|
And the post with title "Houston we have a problem" has a ribbon for pinned posts
|
||||||
|
|
||||||
|
Scenario: Ordinary users cannot pin a post
|
||||||
|
Given I am logged in with a "user" role
|
||||||
|
When I open the content menu of post "Yet another post"
|
||||||
|
Then there is no button to pin a post
|
||||||
|
|
||||||
|
Scenario: Admins are allowed to pin a post
|
||||||
|
Given I am logged in with a "admin" role
|
||||||
|
And I open the content menu of post "Yet another post"
|
||||||
|
When I click on 'Pin post'
|
||||||
|
Then I see a toaster with "Post pinned successfully"
|
||||||
|
And the first post on the landing page has the title:
|
||||||
|
"""
|
||||||
|
Yet another post
|
||||||
|
"""
|
||||||
|
And the post with title "Yet another post" has a ribbon for pinned posts
|
||||||
@ -44,3 +44,31 @@ Then("I should see an abreviated version of my comment", () => {
|
|||||||
Then("the editor should be cleared", () => {
|
Then("the editor should be cleared", () => {
|
||||||
cy.get(".ProseMirror p").should("have.class", "is-empty");
|
cy.get(".ProseMirror p").should("have.class", "is-empty");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
When("I open the content menu of post {string}", (title)=> {
|
||||||
|
cy.contains('.post-card', title)
|
||||||
|
.find('.content-menu .base-button')
|
||||||
|
.click()
|
||||||
|
})
|
||||||
|
|
||||||
|
When("I click on 'Pin post'", (string)=> {
|
||||||
|
cy.get("a.ds-menu-item-link").contains("Pin post")
|
||||||
|
.click()
|
||||||
|
})
|
||||||
|
|
||||||
|
Then("there is no button to pin a post", () => {
|
||||||
|
cy.get("a.ds-menu-item-link")
|
||||||
|
.should('contain', "Report Post") // sanity check
|
||||||
|
.should('not.contain', "Pin post")
|
||||||
|
})
|
||||||
|
|
||||||
|
And("the post with title {string} has a ribbon for pinned posts", (title) => {
|
||||||
|
cy.get("article.post-card").contains(title)
|
||||||
|
.parent()
|
||||||
|
.find("div.ribbon.ribbon--pinned")
|
||||||
|
.should("contain", "Announcement")
|
||||||
|
})
|
||||||
|
|
||||||
|
Then("I see a toaster with {string}", (title) => {
|
||||||
|
cy.get(".iziToast-message").should("contain", title);
|
||||||
|
})
|
||||||
|
|||||||
@ -170,5 +170,4 @@ When("they have a post someone has reported", () => {
|
|||||||
authorId: 'annnoying-user',
|
authorId: 'annnoying-user',
|
||||||
title,
|
title,
|
||||||
});
|
});
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|||||||
@ -212,6 +212,7 @@ Given("we have the following posts in our database:", table => {
|
|||||||
...postAttributes,
|
...postAttributes,
|
||||||
deleted: Boolean(postAttributes.deleted),
|
deleted: Boolean(postAttributes.deleted),
|
||||||
disabled: Boolean(postAttributes.disabled),
|
disabled: Boolean(postAttributes.disabled),
|
||||||
|
pinned: Boolean(postAttributes.pinned),
|
||||||
categoryIds: ['cat-456']
|
categoryIds: ['cat-456']
|
||||||
}
|
}
|
||||||
cy.factory().create("Post", postAttributes);
|
cy.factory().create("Post", postAttributes);
|
||||||
|
|||||||
@ -132,7 +132,7 @@ export default {
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
isPinned() {
|
isPinned() {
|
||||||
return this.post && this.post.pinnedBy
|
return this.post && this.post.pinned
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|||||||
@ -52,6 +52,7 @@ export const postFragment = gql`
|
|||||||
}
|
}
|
||||||
pinnedAt
|
pinnedAt
|
||||||
imageAspectRatio
|
imageAspectRatio
|
||||||
|
pinned
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|||||||
@ -413,8 +413,8 @@
|
|||||||
"name": "Take action"
|
"name": "Take action"
|
||||||
},
|
},
|
||||||
"menu": {
|
"menu": {
|
||||||
"edit": "Edit Post",
|
"edit": "Edit post",
|
||||||
"delete": "Delete Post",
|
"delete": "Delete post",
|
||||||
"pin": "Pin post",
|
"pin": "Pin post",
|
||||||
"pinnedSuccessfully": "Post pinned successfully!",
|
"pinnedSuccessfully": "Post pinned successfully!",
|
||||||
"unpin": "Unpin post",
|
"unpin": "Unpin post",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user