show view due dates button for student view checkpoints

flag=react_discussions_post
flag=discussion_create
flag=discussion_checkpoints
fixes VICE-4199

Change-Id: Ifb38282b822ff2f400a04e089aeb240cc0b18367

important things to note:
- for all scenarios, show due dates (number)
now only says View Due Dates to match figma
and latest product decisions

test plan:
- create a checkpointed discussion
- as a student, view the discussion
- verify you see a View Due Dates button
- verify than when you click on it,
you see an empty tray
(contents will be introduced in a different ticket)

Change-Id: I47b965857d552e38c776e1101149033fb5fcaeda
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/345889
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Samuel Lee <samuel.lee@instructure.com>
QA-Review: Chawn Neal <chawn.neal@instructure.com>
Product-Review: Sam Garza <sam.garza@instructure.com>
This commit is contained in:
Caleb Guanzon 2024-04-22 11:44:02 -06:00
parent b7d1a79f50
commit 5213903e17
9 changed files with 134 additions and 30 deletions

View File

@ -70,7 +70,7 @@ describe "discussions overrides" do
it "shows correct assignment dates in the tray" do
get "/courses/#{@course.id}/discussion_topics/#{@discussion_topic.id}"
fj("button:contains('Show Due Dates (2)')").click
fj("button:contains('View Due Dates')").click
rows = ff("tr[data-testid='assignment-override-row']")
expect(rows[0].text).to eq "Dec 17, 2016 10am New Section Dec 14, 2016 10am Dec 18, 2016 10am"
expect(rows[1].text).to eq "Dec 16, 2016 10am Everyone Else No Start Date No End Date"
@ -80,7 +80,7 @@ describe "discussions overrides" do
@course.enable_course_paces = true
@course.save!
get "/courses/#{@course.id}/discussion_topics/#{@discussion_topic.id}"
fj("button:contains('Show Due Dates (2)')").click
fj("button:contains('View Due Dates')").click
expect(f('[data-testid="CoursePacingNotice"]')).to be_displayed
end
end

View File

@ -22,6 +22,7 @@ import {arrayOf, bool, number, shape, string} from 'prop-types'
import {AssignmentOverride} from './AssignmentOverride'
import {AssessmentRequest} from './AssessmentRequest'
import {PeerReviews} from './PeerReviews'
import {Submission} from './Submission'
export const Assignment = {
fragment: gql`
@ -39,6 +40,11 @@ export const Assignment = {
...AssignmentOverride
}
}
mySubAssignmentSubmissionsConnection {
nodes {
...Submission
}
}
assessmentRequestsForCurrentUser {
...AssessmentRequest
}
@ -47,6 +53,7 @@ export const Assignment = {
}
}
${AssignmentOverride.fragment}
${Submission.fragment}
${AssessmentRequest.fragment}
${PeerReviews.fragment}
`,
@ -61,6 +68,7 @@ export const Assignment = {
restrictQuantitativeData: bool,
pointsPossible: number,
assignmentOverrides: shape({nodes: arrayOf(AssignmentOverride.shape)}),
mySubAssignmentSubmissionsConnection: shape({nodes: arrayOf(Submission.shape)}),
assessmentRequest: arrayOf(AssessmentRequest.shape),
peerReviews: PeerReviews.shape,
}),
@ -78,6 +86,10 @@ export const Assignment = {
nodes: [AssignmentOverride.mock()],
__typename: 'AssignmentOverrideConnection',
},
mySubAssignmentSubmissionsConnection = {
nodes: [],
__typename: 'mySubAssignmentSubmissionsConnection',
},
assessmentRequestsForCurrentUser = [AssessmentRequest.mock()],
peerReviews = PeerReviews.mock(),
} = {}) => ({
@ -89,6 +101,7 @@ export const Assignment = {
onlyVisibleToOverrides,
pointsPossible,
assignmentOverrides,
mySubAssignmentSubmissionsConnection,
assessmentRequestsForCurrentUser,
restrictQuantitativeData,
peerReviews,
@ -109,5 +122,9 @@ export const DefaultMocks = {
nodes: [AssignmentOverride.mock()],
__typename: 'AssignmentOverrideConnection',
},
mySubAssignmentSubmissionsConnection: {
nodes: [],
__typename: 'mySubAssignmentSubmissionsConnection',
},
}),
}

View File

@ -0,0 +1,55 @@
/*
* Copyright (C) 2024 - present Instructure, Inc.
*
* This file is part of Canvas.
*
* Canvas is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, version 3 of the License.
*
* Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import gql from 'graphql-tag'
import {shape, string} from 'prop-types'
export const Submission = {
fragment: gql`
fragment Submission on Submission {
id
_id
submissionStatus
subAssignmentTag
cachedDueDate
}
`,
shape: shape({
id: string,
_id: string,
submissionStatus: string,
subAssignmentTag: string,
cachedDueDate: string,
}),
mock: ({
id = 'BXMzaWdebTVubC0x',
_id = '3',
submissionStatus = 'submitted',
subAssignmentTag = 'reply_to_topic',
cachedDueDate = null,
} = {}) => ({
id,
_id,
submissionStatus,
subAssignmentTag,
cachedDueDate,
__typename: 'Submission',
}),
}

View File

@ -60,7 +60,9 @@ export function AssignmentAvailabilityContainer({...props}) {
return (
<>
{props.inPacedCourse || (props.isAdmin && assignmentOverrides.length > 1) ? (
{props.inPacedCourse ||
(props.isAdmin && assignmentOverrides.length > 1) ||
props.assignment.mySubAssignmentSubmissionsConnection?.nodes?.length > 0 ? (
<AssignmentMultipleAvailabilityWindows
assignmentOverrides={assignmentOverrides}
onSetDueDateTrayOpen={setDueDateTrayOpen}

View File

@ -53,6 +53,25 @@ const mockOverrides = [
},
]
const mockSubAssignmentSubmissions = [
{
id: 'BXMzaWdebTVubC0x',
_id: '4',
cachedDueDate: null,
submissionStatus: 'submitted',
submittedAt: '2024-04-16T14:05:16-06:00',
subAssignmentTag: 'reply_to_topic',
},
{
id: 'BXMzaWdebTVubC0j',
_id: '3',
cachedDueDate: null,
submissionStatus: 'submitted',
submittedAt: '2024-04-18T14:05:16-06:00',
subAssignmentTag: 'reply_to_entry',
},
]
beforeAll(() => {
window.matchMedia = jest.fn().mockImplementation(() => {
return {
@ -91,19 +110,34 @@ describe('AssignmentAvailabilityContainer', () => {
expect(queryByText('Available from Mar 24, 2021 until Apr 4, 2021')).toBeTruthy()
})
it('displays "Show due dates" button when there are overrides', () => {
it('displays "View Due Dates" button when there are overrides', () => {
const {getByText} = setup({
assignmentOverrides: {nodes: mockOverrides},
})
expect(getByText('Show Due Dates (4)')).toBeTruthy()
expect(getByText('View Due Dates')).toBeTruthy()
})
it('displays "View Due Dates" when there are subAssignmentSubmissions', () => {
const {getByText} = render(
<AssignmentAvailabilityContainer
assignment={Assignment.mock({
mySubAssignmentSubmissionsConnection: {nodes: mockSubAssignmentSubmissions},
})}
isAdmin={false}
inPacedCourse={false}
courseId="17"
/>
)
expect(getByText('View Due Dates')).toBeTruthy()
})
it('displays tray and correctly formatted dates', async () => {
const {queryByText, findByText, findAllByTestId} = setup({
assignmentOverrides: {nodes: mockOverrides},
})
expect(queryByText('Show Due Dates (4)')).toBeTruthy()
fireEvent.click(queryByText('Show Due Dates (4)'))
expect(queryByText('View Due Dates')).toBeTruthy()
fireEvent.click(queryByText('View Due Dates'))
expect(await findAllByTestId('assignment-override-row')).toBeTruthy()
expect(await findByText('Sep 4, 2021 5:59am')).toBeTruthy()
})
@ -115,8 +149,8 @@ describe('AssignmentAvailabilityContainer', () => {
const {queryByText, findByText} = setup({
assignmentOverrides: {nodes: mockOverrides},
})
expect(queryByText('Show Due Dates (4)')).toBeTruthy()
fireEvent.click(queryByText('Show Due Dates (4)'))
expect(queryByText('View Due Dates')).toBeTruthy()
fireEvent.click(queryByText('View Due Dates'))
expect(await findByText('No Due Date')).toBeTruthy()
expect(await findByText('No Start Date')).toBeTruthy()
expect(await findByText('No End Date')).toBeTruthy()
@ -130,11 +164,11 @@ describe('AssignmentAvailabilityContainer', () => {
}))
})
it('displays "Show due dates" button when there are overrides', () => {
it('displays "View Due Dates" button when there are overrides', () => {
const {queryByText} = setup({
assignmentOverrides: {nodes: mockOverrides},
})
expect(queryByText('Due Dates (4)')).toBeTruthy()
expect(queryByText('Due Dates')).toBeTruthy()
})
it('displays due date when there are no overrides', () => {
@ -164,7 +198,7 @@ describe('AssignmentAvailabilityContainer', () => {
expect(getByTestId('assignment-override-row')).toBeTruthy()
})
it("due date tray doesn't show assignment context when not admin", () => {
it("due date tray doesn't show assignment context when not admin and no subAssignmentSubmissions", () => {
const {queryByText, getByText, queryByTestId} = setup({
assignmentOverrides: {nodes: []},
isAdmin: false,
@ -188,7 +222,7 @@ describe('AssignmentAvailabilityContainer', () => {
/>
)
act(() => {
getByRole('button', {name: 'Show Due Dates (1)'}).click()
getByRole('button', {name: 'View Due Dates'}).click()
})
expect(await findByTestId('CoursePacingNotice')).toBeInTheDocument()
@ -207,7 +241,7 @@ describe('AssignmentAvailabilityContainer', () => {
/>
)
act(() => {
getByRole('button', {name: 'Show Due Dates (4)'}).click()
getByRole('button', {name: 'View Due Dates'}).click()
})
expect(await findByTestId('CoursePacingNotice')).toBeInTheDocument()

View File

@ -44,15 +44,11 @@ export function AssignmentMultipleAvailabilityWindows({...props}) {
query={responsiveQuerySizes({tablet: true, desktop: true})}
props={{
tablet: {
text: I18n.t('Due Dates (%{dueDateCount})', {
dueDateCount: props.assignmentOverrides.length,
}),
text: I18n.t('Due Dates'),
textSize: 'x-small',
},
desktop: {
text: I18n.t('Show Due Dates (%{dueDateCount})', {
dueDateCount: props.assignmentOverrides.length,
}),
text: I18n.t('View Due Dates'),
textSize: 'small',
},
}}

View File

@ -84,7 +84,7 @@ describe('AssignmentAvailabilityContainer', () => {
describe('desktop', () => {
it('should render', () => {
const container = setup()
expect(container.getByText('Show Due Dates (3)')).toBeInTheDocument()
expect(container.getByText('View Due Dates')).toBeInTheDocument()
})
})
@ -97,7 +97,7 @@ describe('AssignmentAvailabilityContainer', () => {
it('should render', () => {
const container = setup()
expect(container.getByText('Due Dates (3)')).toBeInTheDocument()
expect(container.getByText('Due Dates')).toBeInTheDocument()
})
})
})

View File

@ -150,15 +150,15 @@ describe('DiscussionDetails', () => {
expect(queryByText('Available from Mar 24, 2021 until Apr 4, 2021')).toBeTruthy()
})
it('displays "Show due dates" button when there are overrides', () => {
it('displays "View due dates" button when there are overrides', () => {
const {getByText} = setup({}, mockOverrides)
expect(getByText('Show Due Dates (4)')).toBeTruthy()
expect(getByText('View Due Dates')).toBeTruthy()
})
it('displays tray and correctly formatted dates', async () => {
const {queryByText, findByText, findAllByTestId} = setup({}, mockOverrides)
expect(queryByText('Show Due Dates (4)')).toBeTruthy()
fireEvent.click(queryByText('Show Due Dates (4)'))
expect(queryByText('View Due Dates')).toBeTruthy()
fireEvent.click(queryByText('View Due Dates'))
expect(await findAllByTestId('assignment-override-row')).toBeTruthy()
expect(await findByText('Sep 4, 2021 5:59am')).toBeTruthy()
})
@ -168,8 +168,8 @@ describe('DiscussionDetails', () => {
mockOverrides[2].unlockAt = null
mockOverrides[2].lockAt = null
const {queryByText, findByText} = setup({}, mockOverrides)
expect(queryByText('Show Due Dates (4)')).toBeTruthy()
fireEvent.click(queryByText('Show Due Dates (4)'))
expect(queryByText('View Due Dates')).toBeTruthy()
fireEvent.click(queryByText('View Due Dates'))
expect(await findByText('No Due Date')).toBeTruthy()
expect(await findByText('No Start Date')).toBeTruthy()
expect(await findByText('No End Date')).toBeTruthy()
@ -222,7 +222,7 @@ describe('DiscussionDetails', () => {
it('displays "Show due dates" button when there are overrides', () => {
const {queryByText} = setup({}, mockOverrides)
expect(queryByText('Due Dates (4)')).toBeTruthy()
expect(queryByText('Due Dates')).toBeTruthy()
})
describe('Restrict Quantitative Data is true', () => {
const mockTopic = Discussion.mock({

View File

@ -459,7 +459,7 @@ describe('DiscussionTopicContainer', () => {
it('Should find "Show Due Dates" link button', async () => {
const props = {discussionTopic: Discussion.mock({})}
const container = setup(props)
expect(await container.findByText('Show Due Dates (2)')).toBeTruthy()
expect(await container.findByText('View Due Dates')).toBeTruthy()
})
it('Should find due date text for "assignment override 3"', async () => {