Merge branch 'develop' into greenkeeper/react-test-renderer-16.1.1
This commit is contained in:
21 files changed
+190
-74
No files matched your search
+5
-5
@@ -42,11 +42,11 @@
|
||||
"copy-webpack-plugin": "^4.0.1",
|
||||
"css-loader": "^0.28.7",
|
||||
"enzyme": "^3.1.0",
|
||||
"enzyme-adapter-react-16": "1.0.4",
|
||||
"enzyme-adapter-react-16": "1.1.0",
|
||||
"eslint": "^4.7.1",
|
||||
"eslint-config-scratch": "^5.0.0",
|
||||
"eslint-plugin-import": "^2.7.0",
|
||||
"eslint-plugin-react": "^7.2.1",
|
||||
"eslint-plugin-react": "^7.5.1",
|
||||
"file-loader": "1.1.5",
|
||||
"get-float-time-domain-data": "0.1.0",
|
||||
"gh-pages": "github:rschamp/gh-pages#publish-branch-to-subfolder",
|
||||
@@ -67,9 +67,9 @@
|
||||
"prop-types": "^15.5.10",
|
||||
"raf": "^3.4.0",
|
||||
"raw-loader": "0.5.1",
|
||||
"react": "16.1.0",
|
||||
"react": "16.1.1",
|
||||
"react-contextmenu": "2.8.0",
|
||||
"react-dom": "16.1.0",
|
||||
"react-dom": "16.1.1",
|
||||
"react-draggable": "3.0.3",
|
||||
"react-intl": "2.4.0",
|
||||
"react-intl-redux": "0.7.0",
|
||||
@@ -77,7 +77,7 @@
|
||||
"react-redux": "5.0.6",
|
||||
"react-responsive": "3.0.0",
|
||||
"react-style-proptype": "3.1.0",
|
||||
"react-tabs": "2.1.0",
|
||||
"react-tabs": "2.1.1",
|
||||
"react-test-renderer": "16.1.1",
|
||||
"redux": "3.7.0",
|
||||
"redux-mock-store": "^1.2.3",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@import "../../css/colors.css";
|
||||
@import "../../css/units.css";
|
||||
|
||||
.wrapper {
|
||||
width: 150px;
|
||||
@@ -51,3 +52,14 @@
|
||||
min-height: 5rem;
|
||||
margin: 1rem auto;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: $full-size-paint) {
|
||||
.wrapper {
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
.list-item {
|
||||
width: 4rem;
|
||||
min-height: 4rem;
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import closeIcon from './icon--close.svg';
|
||||
|
||||
const CloseButton = props => (
|
||||
<div
|
||||
aria-label="Close"
|
||||
className={classNames(
|
||||
styles.closeButton,
|
||||
props.className,
|
||||
@@ -15,6 +16,7 @@ const CloseButton = props => (
|
||||
[styles.large]: props.size === CloseButton.SIZE_LARGE
|
||||
}
|
||||
)}
|
||||
role="button"
|
||||
onClick={props.onClick}
|
||||
>
|
||||
<img
|
||||
|
||||
@@ -11,6 +11,7 @@ const IconButton = ({
|
||||
}) => (
|
||||
<div
|
||||
className={classNames(styles.container, className)}
|
||||
role="button"
|
||||
onClick={onClick}
|
||||
>
|
||||
<img
|
||||
|
||||
@@ -22,3 +22,7 @@
|
||||
color: #3373cc;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
.language-select:focus {
|
||||
border: 1px solid white;
|
||||
}
|
||||
@@ -62,6 +62,11 @@
|
||||
border-bottom-left-radius: $form-radius;
|
||||
}
|
||||
|
||||
.radio-left:focus {
|
||||
border-color: #4c97ff;
|
||||
box-shadow: inset 0 0 0 -2px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.radio-right {
|
||||
border-bottom: 1px solid $form-border;
|
||||
border-top: 1px solid $form-border;
|
||||
@@ -70,6 +75,11 @@
|
||||
border-bottom-right-radius: $form-radius;
|
||||
}
|
||||
|
||||
.radio-right:focus {
|
||||
border-color: #4c97ff;
|
||||
box-shadow: inset 0 0 0 -2px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
@@ -54,6 +54,7 @@ class SpriteInfo extends React.Component {
|
||||
<MediaQuery minWidth={layout.fullSizeMinWidth}>
|
||||
<div className={styles.iconWrapper}>
|
||||
<img
|
||||
aria-hidden="true"
|
||||
className={classNames(styles.xIcon, styles.icon)}
|
||||
src={xIcon}
|
||||
/>
|
||||
@@ -76,6 +77,7 @@ class SpriteInfo extends React.Component {
|
||||
<MediaQuery minWidth={layout.fullSizeMinWidth}>
|
||||
<div className={styles.iconWrapper}>
|
||||
<img
|
||||
aria-hidden="true"
|
||||
className={classNames(styles.yIcon, styles.icon)}
|
||||
src={yIcon}
|
||||
/>
|
||||
@@ -116,6 +118,7 @@ class SpriteInfo extends React.Component {
|
||||
)}
|
||||
tabIndex="4"
|
||||
onClick={this.props.onClickVisible}
|
||||
onKeyPress={this.props.onPressVisible}
|
||||
>
|
||||
<img
|
||||
className={styles.icon}
|
||||
@@ -132,8 +135,9 @@ class SpriteInfo extends React.Component {
|
||||
[styles.isDisabled]: this.props.disabled
|
||||
}
|
||||
)}
|
||||
tabIndex="4"
|
||||
tabIndex="5"
|
||||
onClick={this.props.onClickNotVisible}
|
||||
onKeyPress={this.props.onPressNotVisible}
|
||||
>
|
||||
<img
|
||||
className={styles.icon}
|
||||
@@ -151,7 +155,7 @@ class SpriteInfo extends React.Component {
|
||||
small
|
||||
disabled={this.props.disabled}
|
||||
label="Direction"
|
||||
tabIndex="5"
|
||||
tabIndex="6"
|
||||
type="text"
|
||||
value={this.props.disabled ? '' : this.props.direction}
|
||||
onSubmit={this.props.onChangeDirection}
|
||||
@@ -200,6 +204,8 @@ SpriteInfo.propTypes = {
|
||||
onChangeY: PropTypes.func,
|
||||
onClickNotVisible: PropTypes.func,
|
||||
onClickVisible: PropTypes.func,
|
||||
onPressNotVisible: PropTypes.func,
|
||||
onPressVisible: PropTypes.func,
|
||||
rotationStyle: PropTypes.oneOf(ROTATION_STYLES),
|
||||
visible: PropTypes.bool,
|
||||
x: PropTypes.oneOfType([
|
||||
|
||||
@@ -172,6 +172,11 @@ class Blocks extends React.Component {
|
||||
this.workspace.reportValue(data.id, data.value);
|
||||
}
|
||||
onWorkspaceUpdate (data) {
|
||||
// When we change sprites, update the toolbox to have the new sprite's blocks
|
||||
if (this.props.vm.editingTarget) {
|
||||
this.props.updateToolboxState(makeToolboxXML(this.props.vm.editingTarget.id));
|
||||
}
|
||||
|
||||
if (this.props.vm.editingTarget && !this.state.workspaceMetrics[this.props.vm.editingTarget.id]) {
|
||||
this.onWorkspaceMetricsChange();
|
||||
}
|
||||
@@ -179,6 +184,8 @@ class Blocks extends React.Component {
|
||||
// Remove and reattach the workspace listener (but allow flyout events)
|
||||
this.workspace.removeChangeListener(this.props.vm.blockListener);
|
||||
const dom = this.ScratchBlocks.Xml.textToDom(data.xml);
|
||||
// @todo This line rerenders toolbox, and the change in the toolbox XML also rerenders the toolbox.
|
||||
// We should only rerender the toolbox once. See https://github.com/LLK/scratch-gui/issues/901
|
||||
this.ScratchBlocks.Xml.clearWorkspaceAndLoadFromXml(dom, this.workspace);
|
||||
this.workspace.addChangeListener(this.props.vm.blockListener);
|
||||
|
||||
@@ -193,8 +200,8 @@ class Blocks extends React.Component {
|
||||
handleExtensionAdded (blocksInfo) {
|
||||
this.ScratchBlocks.defineBlocksWithJsonArray(blocksInfo.map(blockInfo => blockInfo.json));
|
||||
const dynamicBlocksXML = this.props.vm.runtime.getBlocksXML();
|
||||
const toolboxXML = makeToolboxXML(dynamicBlocksXML);
|
||||
this.props.onExtensionAdded(toolboxXML);
|
||||
const toolboxXML = makeToolboxXML(this.props.vm.editingTarget.id, dynamicBlocksXML);
|
||||
this.props.updateToolboxState(toolboxXML);
|
||||
}
|
||||
handleCategorySelected (categoryName) {
|
||||
this.workspace.toolbox_.setSelectedCategoryByName(categoryName);
|
||||
@@ -220,7 +227,7 @@ class Blocks extends React.Component {
|
||||
vm,
|
||||
isVisible,
|
||||
onActivateColorPicker,
|
||||
onExtensionAdded,
|
||||
updateToolboxState,
|
||||
onRequestCloseExtensionLibrary,
|
||||
toolboxXML,
|
||||
...props
|
||||
@@ -257,7 +264,6 @@ Blocks.propTypes = {
|
||||
extensionLibraryVisible: PropTypes.bool,
|
||||
isVisible: PropTypes.bool,
|
||||
onActivateColorPicker: PropTypes.func,
|
||||
onExtensionAdded: PropTypes.func,
|
||||
onRequestCloseExtensionLibrary: PropTypes.func,
|
||||
options: PropTypes.shape({
|
||||
media: PropTypes.string,
|
||||
@@ -281,6 +287,7 @@ Blocks.propTypes = {
|
||||
comments: PropTypes.bool
|
||||
}),
|
||||
toolboxXML: PropTypes.string,
|
||||
updateToolboxState: PropTypes.func,
|
||||
vm: PropTypes.instanceOf(VM).isRequired
|
||||
};
|
||||
|
||||
@@ -322,11 +329,11 @@ const mapStateToProps = state => ({
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
onActivateColorPicker: callback => dispatch(activateColorPicker(callback)),
|
||||
onExtensionAdded: toolboxXML => {
|
||||
dispatch(updateToolbox(toolboxXML));
|
||||
},
|
||||
onRequestCloseExtensionLibrary: () => {
|
||||
dispatch(closeExtensionLibrary());
|
||||
},
|
||||
updateToolboxState: toolboxXML => {
|
||||
dispatch(updateToolbox(toolboxXML));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -52,20 +52,18 @@ class SoundTab extends React.Component {
|
||||
|
||||
render () {
|
||||
const {
|
||||
editingTarget,
|
||||
sprites,
|
||||
stage,
|
||||
vm,
|
||||
onNewSoundFromLibraryClick,
|
||||
onNewSoundFromRecordingClick
|
||||
} = this.props;
|
||||
|
||||
const target = editingTarget && sprites[editingTarget] ? sprites[editingTarget] : stage;
|
||||
|
||||
if (!target) {
|
||||
if (!vm.editingTarget) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const sounds = target.sounds ? target.sounds.map(sound => (
|
||||
const sprite = vm.editingTarget.sprite;
|
||||
|
||||
const sounds = sprite.sounds ? sprite.sounds.map(sound => (
|
||||
{
|
||||
url: soundIcon,
|
||||
name: sound.name
|
||||
@@ -106,7 +104,7 @@ class SoundTab extends React.Component {
|
||||
onDeleteClick={this.handleDeleteSound}
|
||||
onItemClick={this.handleSelectSound}
|
||||
>
|
||||
{editingTarget && target.sounds && target.sounds.length > 0 ? (
|
||||
{sprite.sounds && sprite.sounds.length > 0 ? (
|
||||
<SoundEditor soundIndex={this.state.selectedSoundIndex} />
|
||||
) : null}
|
||||
{this.props.soundRecorderVisible ? (
|
||||
|
||||
@@ -10,7 +10,9 @@ class SpriteInfo extends React.Component {
|
||||
bindAll(this, [
|
||||
'handleChangeRotationStyle',
|
||||
'handleClickVisible',
|
||||
'handleClickNotVisible'
|
||||
'handleClickNotVisible',
|
||||
'handlePressVisible',
|
||||
'handlePressNotVisible'
|
||||
]);
|
||||
}
|
||||
handleChangeRotationStyle (e) {
|
||||
@@ -24,6 +26,18 @@ class SpriteInfo extends React.Component {
|
||||
e.preventDefault();
|
||||
this.props.onChangeVisibility(false);
|
||||
}
|
||||
handlePressVisible (e) {
|
||||
if (e.key === ' ' || e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
this.props.onChangeVisibility(true);
|
||||
}
|
||||
}
|
||||
handlePressNotVisible (e) {
|
||||
if (e.key === ' ' || e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
this.props.onChangeVisibility(false);
|
||||
}
|
||||
}
|
||||
render () {
|
||||
return (
|
||||
<SpriteInfoComponent
|
||||
@@ -31,6 +45,8 @@ class SpriteInfo extends React.Component {
|
||||
onChangeRotationStyle={this.handleChangeRotationStyle}
|
||||
onClickNotVisible={this.handleClickNotVisible}
|
||||
onClickVisible={this.handleClickVisible}
|
||||
onPressNotVisible={this.handlePressNotVisible}
|
||||
onPressVisible={this.handlePressVisible}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,3 +9,7 @@ $stage-menu-height: 2.75rem;
|
||||
$library-header-height: 4.375rem;
|
||||
|
||||
$form-radius: calc($space / 2);
|
||||
|
||||
/* layout contants from `layout-constants.js` */
|
||||
$full-size: 1095px;
|
||||
$full-size-paint: 1249px;
|
||||
@@ -7,6 +7,11 @@ import ProjectLoaderHOC from './lib/project-loader-hoc.jsx';
|
||||
|
||||
import styles from './index.css';
|
||||
|
||||
if (process.env.NODE_ENV === 'production' && typeof window === 'object') {
|
||||
// Warn before navigating away
|
||||
window.onbeforeunload = () => true;
|
||||
}
|
||||
|
||||
const App = AppStateHOC(ProjectLoaderHOC(GUI));
|
||||
|
||||
const appTarget = document.createElement('div');
|
||||
|
||||
@@ -3,5 +3,6 @@ export default {
|
||||
fullStageHeight: 360,
|
||||
smallerStageWidth: 480 * 0.85,
|
||||
smallerStageHeight: 360 * 0.85,
|
||||
fullSizeMinWidth: 1096
|
||||
fullSizeMinWidth: 1096,
|
||||
fullSizePaintMinWidth: 1250
|
||||
};
|
||||
+47
-30
@@ -2,7 +2,8 @@ const categorySeparator = '<sep gap="36"/>';
|
||||
|
||||
const blockSeparator = '<sep gap="36"/>'; // At default scale, about 28px
|
||||
|
||||
const motion = `
|
||||
const motion = function (targetId) {
|
||||
return `
|
||||
<category name="Motion" colour="#4C97FF" secondaryColour="#3373CC">
|
||||
<block type="motion_movesteps">
|
||||
<value name="STEPS">
|
||||
@@ -120,14 +121,16 @@ const motion = `
|
||||
${blockSeparator}
|
||||
<block type="motion_setrotationstyle"/>
|
||||
${blockSeparator}
|
||||
<block id="xposition" type="motion_xposition"/>
|
||||
<block id="yposition" type="motion_yposition"/>
|
||||
<block id="direction" type="motion_direction"/>
|
||||
<block id="${targetId}_xposition" type="motion_xposition"/>
|
||||
<block id="${targetId}_yposition" type="motion_yposition"/>
|
||||
<block id="${targetId}_direction" type="motion_direction"/>
|
||||
${categorySeparator}
|
||||
</category>
|
||||
`;
|
||||
`;
|
||||
};
|
||||
|
||||
const looks = `
|
||||
const looks = function (targetId) {
|
||||
return `
|
||||
<category name="Looks" colour="#9966FF" secondaryColour="#774DCB">
|
||||
<block type="looks_sayforsecs">
|
||||
<value name="MESSAGE">
|
||||
@@ -229,15 +232,17 @@ const looks = `
|
||||
</value>
|
||||
</block>
|
||||
${blockSeparator}
|
||||
<block id="costumeorder" type="looks_costumeorder"/>
|
||||
<block id="${targetId}_costumeorder" type="looks_costumeorder"/>
|
||||
<block id="backdroporder" type="looks_backdroporder"/>
|
||||
<block id="backdropname" type="looks_backdropname"/>
|
||||
<block id="size" type="looks_size"/>
|
||||
<block id="${targetId}_size" type="looks_size"/>
|
||||
${categorySeparator}
|
||||
</category>
|
||||
`;
|
||||
`;
|
||||
};
|
||||
|
||||
const sound = `
|
||||
const sound = function () {
|
||||
return `
|
||||
<category name="Sound" colour="#D65CD6" secondaryColour="#BD42BD">
|
||||
<block type="sound_play">
|
||||
<value name="SOUND_MENU">
|
||||
@@ -284,9 +289,11 @@ const sound = `
|
||||
<block id="volume" type="sound_volume"/>
|
||||
${categorySeparator}
|
||||
</category>
|
||||
`;
|
||||
`;
|
||||
};
|
||||
|
||||
const events = `
|
||||
const events = function () {
|
||||
return `
|
||||
<category name="Events" colour="#FFD500" secondaryColour="#CC9900">
|
||||
<block type="event_whenflagclicked"/>
|
||||
<block type="event_whenkeypressed">
|
||||
@@ -317,9 +324,11 @@ const events = `
|
||||
</block>
|
||||
${categorySeparator}
|
||||
</category>
|
||||
`;
|
||||
`;
|
||||
};
|
||||
|
||||
const control = `
|
||||
const control = function () {
|
||||
return `
|
||||
<category name="Control" colour="#FFAB19" secondaryColour="#CF8B17">
|
||||
<block type="control_wait">
|
||||
<value name="DURATION">
|
||||
@@ -354,9 +363,11 @@ const control = `
|
||||
<block type="control_delete_this_clone"/>
|
||||
${categorySeparator}
|
||||
</category>
|
||||
`;
|
||||
`;
|
||||
};
|
||||
|
||||
const sensing = `
|
||||
const sensing = function () {
|
||||
return `
|
||||
<category name="Sensing" colour="#4CBFE6" secondaryColour="#2E8EB8">
|
||||
<block type="sensing_touchingobject">
|
||||
<value name="TOUCHINGOBJECTMENU">
|
||||
@@ -422,9 +433,11 @@ const sensing = `
|
||||
<block type="sensing_dayssince2000"/>
|
||||
${categorySeparator}
|
||||
</category>
|
||||
`;
|
||||
`;
|
||||
};
|
||||
|
||||
const operators = `
|
||||
const operators = function () {
|
||||
return `
|
||||
<category name="Operators" colour="#40BF4A" secondaryColour="#389438">
|
||||
<block type="operator_add">
|
||||
<value name="NUM1">
|
||||
@@ -602,33 +615,37 @@ const operators = `
|
||||
</block>
|
||||
${categorySeparator}
|
||||
</category>
|
||||
`;
|
||||
`;
|
||||
};
|
||||
|
||||
const data = `
|
||||
const data = function () {
|
||||
return `
|
||||
<category name="Data" colour="#FF8C1A" secondaryColour="#DB6E00" custom="VARIABLE">
|
||||
</category>
|
||||
`;
|
||||
`;
|
||||
};
|
||||
|
||||
const xmlOpen = '<xml style="display: none">';
|
||||
const xmlClose = '</xml>';
|
||||
|
||||
/**
|
||||
* @param {!string} targetId - The current editing target
|
||||
* @param {string?} categoriesXML - null for default toolbox, or an XML string with <category> elements.
|
||||
* @returns {string} - a ScratchBlocks-style XML document for the contents of the toolbox.
|
||||
*/
|
||||
const makeToolboxXML = function (categoriesXML) {
|
||||
const makeToolboxXML = function (targetId, categoriesXML) {
|
||||
const gap = [categorySeparator];
|
||||
|
||||
const everything = [
|
||||
xmlOpen,
|
||||
motion, gap,
|
||||
looks, gap,
|
||||
sound, gap,
|
||||
events, gap,
|
||||
control, gap,
|
||||
sensing, gap,
|
||||
operators, gap,
|
||||
data
|
||||
motion(targetId), gap,
|
||||
looks(targetId), gap,
|
||||
sound(targetId), gap,
|
||||
events(targetId), gap,
|
||||
control(targetId), gap,
|
||||
sensing(targetId), gap,
|
||||
operators(targetId), gap,
|
||||
data(targetId)
|
||||
];
|
||||
|
||||
if (categoriesXML) {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
const UPDATE_TOOLBOX = 'scratch-gui/toolbox/UPDATE_TOOLBOX';
|
||||
|
||||
import makeToolboxXML from '../lib/make-toolbox-xml';
|
||||
|
||||
const initialState = {
|
||||
toolboxXML: makeToolboxXML()
|
||||
// @todo switch this to make the stage's XML
|
||||
toolboxXML: makeToolboxXML('')
|
||||
};
|
||||
|
||||
const reducer = function (state, action) {
|
||||
|
||||
@@ -4,7 +4,7 @@ import bindAll from 'lodash.bindall';
|
||||
import 'chromedriver'; // register path
|
||||
import webdriver from 'selenium-webdriver';
|
||||
|
||||
const {By, until} = webdriver;
|
||||
const {By, until, Button} = webdriver;
|
||||
|
||||
class SeleniumHelper {
|
||||
constructor () {
|
||||
@@ -15,7 +15,9 @@ class SeleniumHelper {
|
||||
'findByText',
|
||||
'findByXpath',
|
||||
'getDriver',
|
||||
'getLogs'
|
||||
'getLogs',
|
||||
'loadUri',
|
||||
'rightClickText'
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -34,6 +36,14 @@ class SeleniumHelper {
|
||||
return this.findByXpath(`//body//${scope || '*'}//*[contains(text(), '${text}')]`);
|
||||
}
|
||||
|
||||
loadUri (uri) {
|
||||
return this.driver
|
||||
.get(`file://${uri}`)
|
||||
.then(() => (
|
||||
this.driver.executeScript('window.onbeforeunload = undefined;')
|
||||
));
|
||||
}
|
||||
|
||||
clickXpath (xpath) {
|
||||
return this.findByXpath(xpath).then(el => el.click());
|
||||
}
|
||||
@@ -42,6 +52,12 @@ class SeleniumHelper {
|
||||
return this.findByText(text, scope).then(el => el.click());
|
||||
}
|
||||
|
||||
rightClickText (text, scope) {
|
||||
return this.findByText(text, scope).then(el => this.driver.actions()
|
||||
.click(el, Button.RIGHT)
|
||||
.perform());
|
||||
}
|
||||
|
||||
clickButton (text) {
|
||||
return this.clickXpath(`//button[contains(text(), '${text}')]`);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,8 @@ const {
|
||||
clickXpath,
|
||||
findByXpath,
|
||||
getDriver,
|
||||
getLogs
|
||||
getLogs,
|
||||
loadUri
|
||||
} = new SeleniumHelper();
|
||||
|
||||
const errorWhitelist = [
|
||||
@@ -31,7 +32,7 @@ describe('player example', () => {
|
||||
|
||||
test('Load a project by ID', async () => {
|
||||
const projectId = '96708228';
|
||||
await driver.get(`file://${uri}#${projectId}`);
|
||||
await loadUri(`${uri}#${projectId}`);
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
await clickXpath('//img[@title="Go"]');
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
@@ -54,7 +55,7 @@ describe('blocks example', () => {
|
||||
|
||||
test('Load a project by ID', async () => {
|
||||
const projectId = '96708228';
|
||||
await driver.get(`file://${uri}#${projectId}`);
|
||||
await loadUri(`${uri}#${projectId}`);
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
await clickXpath('//img[@title="Go"]');
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
@@ -64,7 +65,7 @@ describe('blocks example', () => {
|
||||
});
|
||||
|
||||
test('Change categories', async () => {
|
||||
await driver.get(`file://${uri}`);
|
||||
await loadUri(`${uri}`);
|
||||
await clickText('Looks');
|
||||
await clickText('Sound');
|
||||
await clickText('Events');
|
||||
|
||||
+18
-12
@@ -8,7 +8,9 @@ const {
|
||||
findByText,
|
||||
findByXpath,
|
||||
getDriver,
|
||||
getLogs
|
||||
getLogs,
|
||||
loadUri,
|
||||
rightClickText
|
||||
} = new SeleniumHelper();
|
||||
|
||||
const uri = path.resolve(__dirname, '../../build/index.html');
|
||||
@@ -34,9 +36,8 @@ describe('costumes, sounds and variables', () => {
|
||||
await driver.quit();
|
||||
});
|
||||
|
||||
|
||||
test('Blocks report when clicked in the toolbox', async () => {
|
||||
await driver.get(`file://${uri}`);
|
||||
await loadUri(uri);
|
||||
await clickText('Blocks');
|
||||
await clickText('Operators', blocksTabScope);
|
||||
await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for scroll animation
|
||||
@@ -47,7 +48,7 @@ describe('costumes, sounds and variables', () => {
|
||||
});
|
||||
|
||||
test('Switching sprites updates the block menus', async () => {
|
||||
await driver.get(`file://${uri}`);
|
||||
await loadUri(uri);
|
||||
await clickText('Sound', blocksTabScope);
|
||||
await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for scroll animation
|
||||
// "meow" sound block should be visible
|
||||
@@ -60,7 +61,7 @@ describe('costumes, sounds and variables', () => {
|
||||
});
|
||||
|
||||
test('Adding a costume', async () => {
|
||||
await driver.get(`file://${uri}`);
|
||||
await loadUri(uri);
|
||||
await clickText('Costumes');
|
||||
await clickText('Add Costume');
|
||||
const el = await findByXpath("//input[@placeholder='what are you looking for?']");
|
||||
@@ -73,17 +74,22 @@ describe('costumes, sounds and variables', () => {
|
||||
});
|
||||
|
||||
test('Adding a sound', async () => {
|
||||
await driver.get(`file://${uri}`);
|
||||
await loadUri(uri);
|
||||
await clickText('Sounds');
|
||||
|
||||
// Delete the sound
|
||||
await rightClickText('meow', soundsTabScope);
|
||||
await clickText('delete', soundsTabScope);
|
||||
await driver.switchTo().alert()
|
||||
.accept();
|
||||
|
||||
// Add a sound
|
||||
await clickText('Add Sound');
|
||||
const el = await findByXpath("//input[@placeholder='what are you looking for?']");
|
||||
await el.sendKeys('chom');
|
||||
await clickText('chomp'); // Should close the modal, then click the sounds in the selector
|
||||
await clickText('meow', soundsTabScope);
|
||||
await clickText('chomp', soundsTabScope);
|
||||
await clickXpath('//button[@title="Play"]');
|
||||
await clickText('meow', soundsTabScope);
|
||||
await clickXpath('//button[@title="Play"]');
|
||||
|
||||
await clickText('Louder');
|
||||
await clickText('Softer');
|
||||
@@ -99,7 +105,7 @@ describe('costumes, sounds and variables', () => {
|
||||
|
||||
test('Load a project by ID', async () => {
|
||||
const projectId = '96708228';
|
||||
await driver.get(`file://${uri}#${projectId}`);
|
||||
await loadUri(`${uri}#${projectId}`);
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
await clickXpath('//img[@title="Go"]');
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
@@ -109,7 +115,7 @@ describe('costumes, sounds and variables', () => {
|
||||
});
|
||||
|
||||
test('Creating variables', async () => {
|
||||
await driver.get(`file://${uri}`);
|
||||
await loadUri(uri);
|
||||
await clickText('Blocks');
|
||||
await clickText('Data', blocksTabScope);
|
||||
await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for scroll animation
|
||||
@@ -133,7 +139,7 @@ describe('costumes, sounds and variables', () => {
|
||||
});
|
||||
|
||||
test('Importing extensions', async () => {
|
||||
await driver.get(`file://${uri}`);
|
||||
await loadUri(uri);
|
||||
await clickText('Blocks');
|
||||
await clickText('Extensions');
|
||||
await clickText('Pen', modalScope); // Modal closes
|
||||
|
||||
@@ -4,6 +4,7 @@ exports[`IconButtonComponent matches snapshot 1`] = `
|
||||
<div
|
||||
className="custom-class-name"
|
||||
onClick={[Function]}
|
||||
role="button"
|
||||
>
|
||||
<img
|
||||
className={undefined}
|
||||
|
||||
@@ -341,6 +341,7 @@ exports[`Sound Editor Component matches snapshot 1`] = `
|
||||
<div
|
||||
className=""
|
||||
onClick={[Function]}
|
||||
role="button"
|
||||
>
|
||||
<img
|
||||
className={undefined}
|
||||
@@ -357,6 +358,7 @@ exports[`Sound Editor Component matches snapshot 1`] = `
|
||||
<div
|
||||
className=""
|
||||
onClick={[Function]}
|
||||
role="button"
|
||||
>
|
||||
<img
|
||||
className={undefined}
|
||||
@@ -373,6 +375,7 @@ exports[`Sound Editor Component matches snapshot 1`] = `
|
||||
<div
|
||||
className=""
|
||||
onClick={[Function]}
|
||||
role="button"
|
||||
>
|
||||
<img
|
||||
className={undefined}
|
||||
@@ -389,6 +392,7 @@ exports[`Sound Editor Component matches snapshot 1`] = `
|
||||
<div
|
||||
className=""
|
||||
onClick={[Function]}
|
||||
role="button"
|
||||
>
|
||||
<img
|
||||
className={undefined}
|
||||
@@ -405,6 +409,7 @@ exports[`Sound Editor Component matches snapshot 1`] = `
|
||||
<div
|
||||
className=""
|
||||
onClick={[Function]}
|
||||
role="button"
|
||||
>
|
||||
<img
|
||||
className={undefined}
|
||||
@@ -421,6 +426,7 @@ exports[`Sound Editor Component matches snapshot 1`] = `
|
||||
<div
|
||||
className=""
|
||||
onClick={[Function]}
|
||||
role="button"
|
||||
>
|
||||
<img
|
||||
className={undefined}
|
||||
@@ -437,6 +443,7 @@ exports[`Sound Editor Component matches snapshot 1`] = `
|
||||
<div
|
||||
className=""
|
||||
onClick={[Function]}
|
||||
role="button"
|
||||
>
|
||||
<img
|
||||
className={undefined}
|
||||
|
||||
@@ -12,8 +12,10 @@ exports[`SpriteSelectorItemComponent matches snapshot when selected 1`] = `
|
||||
onTouchStart={[Function]}
|
||||
>
|
||||
<div
|
||||
aria-label="Close"
|
||||
className=""
|
||||
onClick={[Function]}
|
||||
role="button"
|
||||
>
|
||||
<img
|
||||
className={undefined}
|
||||
|
||||
Reference in new issue
Block a user