Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,20 +1,76 @@
// import React from 'react';
// import Renderer from 'react-test-renderer/shallow';
// import SubmissionManagement from 'components/SubmissionManagement/SubmissionManagement';

// FIXME: Fix the tests for the settings page
test('Matches shallow shapshot', () => {
expect(true).toBeTruthy();
// const renderer = new Renderer();
// renderer.render((
// <SubmissionManagement
// challenge={{
// track: 'Challenge Track',
// }}
// submissions={[
//
// ]}
// />
// ));
// expect(renderer.getRenderOutput()).toMatchSnapshot();
import { shallow } from 'enzyme';
import React from 'react';
import { PrimaryButton } from 'topcoder-react-ui-kit';

import SubmissionManagement from 'components/SubmissionManagement/SubmissionManagement';

/**
* Renders the regular My Submissions page with an open Design upload phase.
*
* @param {Object} propOverrides Optional component prop replacements.
* @return {ShallowWrapper} Rendered Submission Management component.
* @throws {Error} Propagates errors raised while shallow-rendering the component.
*/
function renderSubmissionManagement(propOverrides = {}) {
return shallow(
<SubmissionManagement
challenge={{
name: 'Design challenge',
phases: [{
isOpen: true,
name: 'Submission',
scheduledEndDate: '2030-08-20T00:00:00.000Z',
scheduledStartDate: '2030-08-10T00:00:00.000Z',
}],
status: 'ACTIVE',
track: 'Design',
}}
challengeUrl="/challenges/challenge-id"
onAddSubmission={jest.fn()}
showDetails={{}}
submissionPhaseStartDate="2030-08-10T00:00:00.000Z"
submissionWorkflowRuns={{}}
{...propOverrides}
/>,
);
}

describe('Submission Management Add Submission action', () => {
test('routes through the authoritative limit handler', () => {
const onAddSubmission = jest.fn();
const wrapper = renderSubmissionManagement({ onAddSubmission });
const button = wrapper.find(PrimaryButton).last();

expect(button.prop('to')).toBe('/challenges/challenge-id/submit');
expect(button.prop('onClick')).toBe(onAddSubmission);
expect(button.prop('disabled')).toBe(false);
});

test('supports checkpoint uploads on the regular My Submissions route', () => {
const wrapper = renderSubmissionManagement({
challenge: {
name: 'Design challenge',
phases: [{
isOpen: true,
name: 'Checkpoint Submission',
scheduledEndDate: '2030-08-20T00:00:00.000Z',
scheduledStartDate: '2030-08-10T00:00:00.000Z',
}],
status: 'ACTIVE',
track: 'Design',
},
});

expect(wrapper.find(PrimaryButton)).toHaveLength(1);
});

test('disables direct routing while the limit lookup is pending', () => {
const wrapper = renderSubmissionManagement({
submissionLimitCheckPending: true,
});
const button = wrapper.find(PrimaryButton).last();

expect(button.prop('disabled')).toBe(true);
expect(button.prop('to')).toBeNull();
});
});
74 changes: 71 additions & 3 deletions __tests__/shared/components/challenge-detail/Header/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ function renderHeader(challengeOverrides = {}, propOverrides = {}) {
numWinners={1}
onSelectorClicked={jest.fn()}
onSort={jest.fn()}
onSubmitChallenge={jest.fn()}
onToggleDeadlines={jest.fn()}
openForRegistrationChallenges={{}}
registerForChallenge={jest.fn()}
Expand Down Expand Up @@ -190,9 +191,10 @@ describe('Challenge detail header actions', () => {
unlimited: 'false',
}),
}],
track: 'Design',
}, {
hasRegistered: true,
mySubmissions: [{ id: 'submission-id' }],
mySubmissions: [{ id: 'submission-id', type: 'CONTEST_SUBMISSION' }],
});
const submitAction = findSubmitAction(output);

Expand All @@ -207,6 +209,7 @@ describe('Challenge detail header actions', () => {
});

test('keeps the submission page available while slots remain', () => {
const onSubmitChallenge = jest.fn();
const output = renderHeader({
metadata: [{
name: 'submissionLimit',
Expand All @@ -216,16 +219,81 @@ describe('Challenge detail header actions', () => {
unlimited: 'false',
}),
}],
track: 'Design',
}, {
hasRegistered: true,
mySubmissions: [{ id: 'submission-id' }],
mySubmissions: [{ id: 'submission-id', type: 'CONTEST_SUBMISSION' }],
onSubmitChallenge,
});
const submitAction = findSubmitAction(output);

expect(submitAction.props.to).toBe('/challenges/challenge-id/submit');
expect(submitAction.props.onClick).toBeUndefined();
expect(submitAction.props.onClick).toBe(onSubmitChallenge);
expect(mockedErrors.fireErrorMessage).not.toHaveBeenCalled();
});

test('does not count a checkpoint submission against the contest limit', () => {
const onSubmitChallenge = jest.fn();
const output = renderHeader({
metadata: [{
name: 'submissionLimit',
value: JSON.stringify({
count: '1',
limit: 'true',
unlimited: 'false',
}),
}],
phases: [
{ isOpen: false, name: 'Checkpoint Submission' },
{ isOpen: true, name: 'Submission' },
],
track: 'Design',
}, {
hasRegistered: true,
mySubmissions: [{ id: 'submission-id', type: 'CHECKPOINT_SUBMISSION' }],
onSubmitChallenge,
});
const submitAction = findSubmitAction(output);

expect(submitAction.props.to).toBe('/challenges/challenge-id/submit');
expect(submitAction.props.onClick).toBe(onSubmitChallenge);
expect(mockedErrors.fireErrorMessage).not.toHaveBeenCalled();
});

test('does not apply Design submission-limit metadata to Development challenges', () => {
const onSubmitChallenge = jest.fn();
const output = renderHeader({
metadata: [{
name: 'submissionLimit',
value: JSON.stringify({
count: '1',
limit: 'true',
unlimited: 'false',
}),
}],
track: 'Development',
}, {
hasRegistered: true,
mySubmissions: [{ id: 'submission-id', type: 'CONTEST_SUBMISSION' }],
onSubmitChallenge,
});
const submitAction = findSubmitAction(output);

expect(submitAction.props.to).toBe('/challenges/challenge-id/submit');
expect(submitAction.props.onClick).toBe(onSubmitChallenge);
expect(mockedErrors.fireErrorMessage).not.toHaveBeenCalled();
});

test('disables submit navigation while the authoritative limit check is pending', () => {
const output = renderHeader({}, {
hasRegistered: true,
submissionLimitCheckPending: true,
});
const submitAction = findSubmitAction(output);

expect(submitAction.props.disabled).toBe(true);
expect(submitAction.props.to).toBeUndefined();
});
});

describe('Challenge detail tab counts', () => {
Expand Down
169 changes: 169 additions & 0 deletions __tests__/shared/containers/SubmissionManagement.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,177 @@
* modification of SubmissionManagement component, that required to wrap
* it into <StaticRouter> element. No time to properly fix it now, thus
* just commented out. */
import { SubmissionManagementPageContainer } from 'containers/SubmissionManagement';
import { getChallengeSubmissions as mockedGetChallengeSubmissions } from 'services/submissions';

jest.mock('services/submissions', () => ({
downloadSubmissions: jest.fn(),
getChallengeSubmissions: jest.fn(),
getSubmissionArtifacts: jest.fn(),
getSubmissionDownloadUrl: jest.fn(),
}));

test.skip('Placeholder', () => {});

/**
* Creates a mounted Submission Management container with Design limit defaults.
*
* @param {Object} propOverrides Optional container prop replacements.
* @return {{container: SubmissionManagementPageContainer, props: Object}} Test container and props.
* @throws Does not throw.
*/
function createSubmissionManagementContainer(propOverrides = {}) {
const props = {
authTokens: {
tokenV3: 'token-v3',
user: { userId: 'member-id' },
},
challenge: {
metadata: [{
name: 'submissionLimit',
value: JSON.stringify({
count: '1',
limit: 'true',
unlimited: 'false',
}),
}],
phases: [{ isOpen: true, name: 'Submission' }],
track: 'Design',
},
challengeId: 'challenge-id',
challengesUrl: '/challenges',
history: { push: jest.fn() },
mySubmissions: [],
...propOverrides,
};
const container = new SubmissionManagementPageContainer(props);
container.isComponentMounted = true;
container.setState = jest.fn((state, callback) => {
container.state = { ...container.state, ...state };
if (callback) callback();
});

return { container, props };
}

describe('Submission Management Add Submission limit', () => {
beforeEach(() => {
mockedGetChallengeSubmissions.mockReset();
});

test('blocks the regular Design route when service history reaches the contest limit', async () => {
mockedGetChallengeSubmissions.mockResolvedValue({
data: [{ id: 'contest-submission' }],
});
const { container, props } = createSubmissionManagementContainer();
const event = { preventDefault: jest.fn() };

await container.onAddSubmission(event);

expect(event.preventDefault).toHaveBeenCalledTimes(1);
expect(mockedGetChallengeSubmissions).toHaveBeenCalledWith(
'token-v3',
'challenge-id',
{
memberId: 'member-id',
type: 'CONTEST_SUBMISSION',
},
);
expect(props.history.push).not.toHaveBeenCalled();
});

test('routes when complete checkpoint history confirms a slot remains', async () => {
mockedGetChallengeSubmissions.mockResolvedValue({ data: [] });
const { container, props } = createSubmissionManagementContainer({
challenge: {
metadata: [{
name: 'submissionLimit',
value: JSON.stringify({
count: '1',
limit: 'true',
unlimited: 'false',
}),
}],
phases: [{ isOpen: true, name: 'Checkpoint Submission' }],
track: 'Design',
},
});

await container.onAddSubmission({ preventDefault: jest.fn() });

expect(mockedGetChallengeSubmissions).toHaveBeenCalledWith(
'token-v3',
'challenge-id',
{
memberId: 'member-id',
type: 'CHECKPOINT_SUBMISSION',
},
);
expect(props.history.push).toHaveBeenCalledWith('/challenges/challenge-id/submit');
});

test('fails closed and releases the pending guard when history lookup fails', async () => {
mockedGetChallengeSubmissions.mockRejectedValue(new Error('network error'));
const { container, props } = createSubmissionManagementContainer();

await container.onAddSubmission({ preventDefault: jest.fn() });

expect(props.history.push).not.toHaveBeenCalled();
expect(container.submissionLimitCheckPending).toBe(false);
expect(container.state.submissionLimitCheckPending).toBe(false);
});

test('leaves unlimited, non-Design, and final-fix links to normal navigation', async () => {
const { container: unlimitedContainer } = createSubmissionManagementContainer({
challenge: {
metadata: [],
phases: [{ isOpen: true, name: 'Submission' }],
track: 'Design',
},
});
const { container: finalFixContainer } = createSubmissionManagementContainer({
challenge: {
metadata: [{
name: 'submissionLimit',
value: JSON.stringify({
count: '1',
limit: 'true',
unlimited: 'false',
}),
}],
phases: [{ isOpen: true, name: 'Final Fix' }],
track: 'Design',
},
});
const { container: developmentContainer } = createSubmissionManagementContainer({
challenge: {
metadata: [{
name: 'submissionLimit',
value: JSON.stringify({
count: '1',
limit: 'true',
unlimited: 'false',
}),
}],
phases: [{ isOpen: true, name: 'Submission' }],
track: 'Development',
},
});
const unlimitedEvent = { preventDefault: jest.fn() };
const finalFixEvent = { preventDefault: jest.fn() };
const developmentEvent = { preventDefault: jest.fn() };

await unlimitedContainer.onAddSubmission(unlimitedEvent);
await finalFixContainer.onAddSubmission(finalFixEvent);
await developmentContainer.onAddSubmission(developmentEvent);

expect(unlimitedEvent.preventDefault).not.toHaveBeenCalled();
expect(finalFixEvent.preventDefault).not.toHaveBeenCalled();
expect(developmentEvent.preventDefault).not.toHaveBeenCalled();
expect(mockedGetChallengeSubmissions).not.toHaveBeenCalled();
});
});

/*
import _ from 'lodash';
import React from 'react';
Expand Down
Loading
Loading