diff --git a/package.json b/package.json index 832f73b31..2f730a6e0 100644 --- a/package.json +++ b/package.json @@ -95,13 +95,13 @@ "react": "16.2.0", "react-dom": "16.2.0", "react-intl": "2.8.0", - "react-modal": "3.1.11", + "react-modal": "3.4.1", "react-onclickoutside": "6.7.1", "react-redux": "5.0.7", "react-responsive": "3.0.0", "react-slick": "0.16.0", "react-string-replace": "0.4.1", - "scratch-gui": "0.1.0-prerelease.20190530174801", + "scratch-gui": "0.1.0-prerelease.20190605185254", "react-telephone-input": "4.3.4", "redux": "3.5.2", "redux-thunk": "2.0.1", diff --git a/src/redux/preview.js b/src/redux/preview.js index 0a3eb2a5d..239a4a93e 100644 --- a/src/redux/preview.js +++ b/src/redux/preview.js @@ -763,11 +763,16 @@ module.exports.getRemixes = id => (dispatch => { }); }); -module.exports.getProjectStudios = id => (dispatch => { + +module.exports.getProjectStudios = (id, ownerUsername, isAdmin, token) => (dispatch => { dispatch(module.exports.setFetchStatus('projectStudios', module.exports.Status.FETCHING)); - api({ - uri: `/projects/${id}/studios` - }, (err, body, res) => { + const opts = { + uri: `${isAdmin ? '/admin' : `/users/${ownerUsername}`}/projects/${id}/studios` + }; + if (token) { + Object.assign(opts, {authentication: token}); + } + api(opts, (err, body, res) => { if (err) { dispatch(module.exports.setFetchStatus('projectStudios', module.exports.Status.ERROR)); dispatch(module.exports.setError(err)); diff --git a/src/views/preview/project-view.jsx b/src/views/preview/project-view.jsx index 903d01fd4..eac5fe7aa 100644 --- a/src/views/preview/project-view.jsx +++ b/src/views/preview/project-view.jsx @@ -160,7 +160,10 @@ class Preview extends React.Component { if (typeof this.props.projectInfo.id === 'undefined') { this.initCounts(0, 0); } else { + const token = this.props.user ? this.props.user.token : null; this.initCounts(this.props.projectInfo.stats.favorites, this.props.projectInfo.stats.loves); + this.props.getProjectStudios(this.props.projectInfo.id, + this.props.authorUsername, this.props.isAdmin, token); if (this.props.projectInfo.remix.parent !== null) { this.props.getParentInfo(this.props.projectInfo.remix.parent); } @@ -216,7 +219,6 @@ class Preview extends React.Component { } this.props.getProjectInfo(this.state.projectId, token); this.props.getRemixes(this.state.projectId, token); - this.props.getProjectStudios(this.state.projectId, token); this.props.getCuratedStudios(username); this.props.getFavedStatus(this.state.projectId, username, token); this.props.getLovedStatus(this.state.projectId, username, token); @@ -228,7 +230,6 @@ class Preview extends React.Component { } this.props.getProjectInfo(this.state.projectId); this.props.getRemixes(this.state.projectId); - this.props.getProjectStudios(this.state.projectId); } } setScreenFromOrientation () { @@ -984,8 +985,8 @@ const mapDispatchToProps = dispatch => ({ getRemixes: id => { dispatch(previewActions.getRemixes(id)); }, - getProjectStudios: id => { - dispatch(previewActions.getProjectStudios(id)); + getProjectStudios: (id, ownerUsername, isAdmin, token) => { + dispatch(previewActions.getProjectStudios(id, ownerUsername, isAdmin, token)); }, getCuratedStudios: (username, token) => { dispatch(previewActions.getCuratedStudios(username, token)); diff --git a/test/integration-cypress/cypress/smoke-tests/test-footer-links.js b/test/integration-cypress/cypress/smoke-tests/test-footer-links.js index d178372fb..3b6fa29f7 100644 --- a/test/integration-cypress/cypress/smoke-tests/test-footer-links.js +++ b/test/integration-cypress/cypress/smoke-tests/test-footer-links.js @@ -71,7 +71,7 @@ describe('test About links in footer', function () { .should('eq', baseUrl + '/jobs'); }); - it('click Press', function (){ + it.skip('click Press', function (){ cy .get('.lists :first-child :nth-child(8) :first-child :first-child') .click(); @@ -112,7 +112,7 @@ describe('test Community links in footer', function () { .should('eq', baseUrl + '/discuss/'); }); - it('click Scratch Wiki', function (){ + it.skip('click Scratch Wiki', function (){ cy .get('.lists :nth-child(2) :nth-child(4) :first-child :first-child') .click(); @@ -247,7 +247,7 @@ describe('test Scratch Family links in footer', function () { cy.visit('/'); }); - it('click ScratchEd', function (){ + it.skip('click ScratchEd', function (){ cy .get('.lists :nth-child(5) :nth-child(2) a') .click(); @@ -256,7 +256,7 @@ describe('test Scratch Family links in footer', function () { .should('match', /^http:\/\/scratched\.gse\.harvard\.edu\/?$/); }); - it('click For ScratchJr', function (){ + it.skip('click For ScratchJr', function (){ cy .get('.lists :nth-child(5) :nth-child(3) a') .click(); @@ -285,7 +285,7 @@ describe('test Scratch Family links in footer', function () { .should('eq', baseUrl + '/conference'); }); - it('click Scratch Foundation', function (){ + it.skip('click Scratch Foundation', function (){ cy .get('.lists :nth-child(5) :nth-child(6) :first-child :first-child') .click(); diff --git a/test/integration/selenium-helpers.js b/test/integration/selenium-helpers.js index 14e8a0a63..1edc54b98 100644 --- a/test/integration/selenium-helpers.js +++ b/test/integration/selenium-helpers.js @@ -12,19 +12,20 @@ const {By, Key, until} = webdriver; class SeleniumHelper { constructor () { bindAll(this, [ - 'getDriver', - 'getSauceDriver', - 'getKey', 'buildDriver', - 'clickXpath', - 'findByXpath', - 'clickText', - 'findText', 'clickButton', - 'findByCss', 'clickCss', - 'urlMatches', - 'getLogs' + 'clickText', + 'clickXpath', + 'dragFromXpathToXpath', + 'findByCss', + 'findByXpath', + 'findText', + 'getKey', + 'getDriver', + 'getLogs', + 'getSauceDriver', + 'urlMatches' ]); } buildDriver (name) { @@ -113,6 +114,16 @@ class SeleniumHelper { return this.findByCss(css).then(el => el.click()); } + dragFromXpathToXpath (startXpath, endXpath) { + return this.findByXpath(startXpath).then(startEl => { + return this.findByXpath(endXpath).then(endEl => { + return this.driver.actions() + .dragAndDrop(startEl, endEl) + .perform(); + }); + }); + } + urlMatches (regex) { return this.driver.wait(until.urlMatches(regex), 1000 * 5); } diff --git a/test/integration/smoke-testing/test_project_page.js b/test/integration/smoke-testing/test_project_page.js new file mode 100644 index 000000000..0ec9f1373 --- /dev/null +++ b/test/integration/smoke-testing/test_project_page.js @@ -0,0 +1,55 @@ +const SeleniumHelper = require('../selenium-helpers.js'); +const helper = new SeleniumHelper(); + +var tap = require('tap'); +const test = tap.test; + +const driver = helper.buildDriver('www-smoke test_sign_in_out_homepage'); + +const { + clickText, + clickXpath, + dragFromXpathToXpath +} = helper; + +const rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; +const projectId = 1; +const projectUrl = `${rootUrl}/projects/${projectId}`; + +tap.plan(3); + +tap.tearDown(function () { + driver.quit(); +}); + +tap.beforeEach(function () { + return driver.get(projectUrl); +}); + +test('Find fullscreen button', t => { + clickXpath('//div[starts-with(@class, "loader_background")]') + .then(() => clickXpath('//div[starts-with(@class, "stage_green-flag-overlay")]')) + .then(() => clickXpath('//img[contains(@alt, "Enter full screen mode")]')) + .then(() => t.end()); +}); + +test('Open and close Copy Link modal', t => { + clickText('Copy Link') + .then(() => clickXpath('//div[contains(@class, "social-label-title")]')) + .then(() => clickXpath('//img[contains(@alt, "close-icon")]')) + .then(() => clickXpath('//img[contains(@alt, "Enter full screen mode")]')) + .then(() => t.end()); +}); + +test('Dragging out of modal should not close modal', t => { + clickXpath('//div[starts-with(@class, "loader_background")]') + .then(() => clickXpath('//div[starts-with(@class, "stage_green-flag-overlay")]')) + .then(() => clickText('Copy Link')) + .then(() => clickXpath('//div[contains(@class, "social-label-title")]')) + .then(() => dragFromXpathToXpath( + '//div[contains(@class, "social-label-title")]', + '//li[contains(@class, "logo")]' + )) + .then(() => clickXpath('//div[contains(@class, "social-label-title")]')) + .then(() => t.end()); +});