diff --git a/package.json b/package.json index e6ef75b48fa2c4d5088cf11f88ad7a0dc3208a2b..5532e798bbba4df7ed6393ebae9a6be11814e523 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "babel-preset-es2015": "^6.22.0", "babel-preset-react": "^6.22.0", "buffer-loader": "0.0.1", - "chromedriver": "2.34.1", + "chromedriver": "2.35.0", "classnames": "2.2.5", "copy-webpack-plugin": "^4.3.0", "css-loader": "^0.28.7", diff --git a/test/helpers/selenium-helper.js b/test/helpers/selenium-helper.js index 44064d5bda1effd5d29eb51f06aab0a5fec6d81f..c8ead90725e7197bf1ab966e94d05a7145ae88e5 100644 --- a/test/helpers/selenium-helper.js +++ b/test/helpers/selenium-helper.js @@ -21,6 +21,17 @@ class SeleniumHelper { ]); } + get scope () { + // List of useful xpath scopes for finding elements + return { + blocksTab: "*[@id='react-tabs-1']", + modal: '*[@class="ReactModalPortal"]', + reportedValue: '*[@class="blocklyDropDownContent"]', + soundsTab: "*[@id='react-tabs-5']", + spriteTile: '*[starts-with(@class,"react-contextmenu-wrapper")]' + }; + } + getDriver () { this.driver = new webdriver.Builder() .forBrowser('chrome') @@ -70,6 +81,12 @@ class SeleniumHelper { } getLogs (whitelist) { + if (!whitelist) { + // Default whitelist + whitelist = [ + 'The play() request was interrupted by a call to pause()' + ]; + } return this.driver.manage() .logs() .get('browser') diff --git a/test/integration/blocks.test.js b/test/integration/blocks.test.js new file mode 100644 index 0000000000000000000000000000000000000000..9f073648882d6e3cad7eb8915edb72bbc3410c95 --- /dev/null +++ b/test/integration/blocks.test.js @@ -0,0 +1,106 @@ +import path from 'path'; +import SeleniumHelper from '../helpers/selenium-helper'; + +const { + clickText, + clickButton, + clickXpath, + findByText, + findByXpath, + getDriver, + getLogs, + loadUri, + scope +} = new SeleniumHelper(); + +const uri = path.resolve(__dirname, '../../build/index.html'); + +let driver; + +describe('Working with the blocks', () => { + beforeAll(() => { + driver = getDriver(); + }); + + afterAll(async () => { + await driver.quit(); + }); + + test('Blocks report when clicked in the toolbox', async () => { + await loadUri(uri); + await clickXpath('//button[@title="tryit"]'); + await clickText('Blocks'); + await clickText('Operators', scope.blocksTab); + await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for scroll animation + await clickText('join', scope.blocksTab); // Click "join <hello> <world>" block + await findByText('helloworld', scope.reportedValue); // Tooltip with result + const logs = await getLogs(); + await expect(logs).toEqual([]); + }); + + test('Switching sprites updates the block menus', async () => { + await loadUri(uri); + await clickXpath('//button[@title="tryit"]'); + await clickText('Sound', scope.blocksTab); + await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for scroll animation + // "Meow" sound block should be visible + await findByText('Meow', scope.blocksTab); + await clickText('Backdrops'); // Switch to the backdrop + // Now "pop" sound block should be visible and motion blocks hidden + await findByText('pop', scope.blocksTab); + await clickText('Motion', scope.blocksTab); + await findByText('Stage selected: no motion blocks'); + + const logs = await getLogs(); + await expect(logs).toEqual([]); + }); + + test('Creating variables', async () => { + await loadUri(uri); + await clickXpath('//button[@title="tryit"]'); + await clickText('Blocks'); + await clickText('Variables', scope.blocksTab); + await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for scroll animation + + // Expect a default variable "my variable" to be visible + await clickText('my\u00A0variable', scope.blocksTab); + await findByText('0', scope.reportedValue); + + await clickText('Make a Variable'); + let el = await findByXpath("//input[@placeholder='']"); + await el.sendKeys('score'); + await clickButton('OK'); + await clickText('Make a Variable'); + el = await findByXpath("//input[@placeholder='']"); + await el.sendKeys('second variable'); + await clickButton('OK'); + + // Make sure reporting works on a new variable + await clickText('Variables', scope.blocksTab); + await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for scroll animation + await clickText('score', scope.blocksTab); + await findByText('0', scope.reportedValue); // Tooltip with result + + const logs = await getLogs(); + await expect(logs).toEqual([]); + }); + + test('Custom procedures', async () => { + await loadUri(uri); + await clickXpath('//button[@title="tryit"]'); + await clickText('My Blocks'); + await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for scroll animation + await clickText('Make a Block'); + // Click on the "add an input" buttons + await clickText('number or text', scope.modal); + await clickText('boolean', scope.modal); + await clickText('Add a label', scope.modal); + await clickText('OK', scope.modal); + + // Make sure a "define" block has been added to the workspace + await findByText('define', scope.blocksTab); + + const logs = await getLogs(); + await expect(logs).toEqual([]); + }); +}); diff --git a/test/integration/costumes.test.js b/test/integration/costumes.test.js new file mode 100644 index 0000000000000000000000000000000000000000..b19576bf2ff8ae6313b595c6b56f628fe11a762a --- /dev/null +++ b/test/integration/costumes.test.js @@ -0,0 +1,49 @@ +import path from 'path'; +import SeleniumHelper from '../helpers/selenium-helper'; + +const { + clickText, + clickXpath, + findByXpath, + getDriver, + getLogs, + loadUri +} = new SeleniumHelper(); + +const uri = path.resolve(__dirname, '../../build/index.html'); + +let driver; + +describe('Working with costumes', () => { + beforeAll(() => { + driver = getDriver(); + }); + + afterAll(async () => { + await driver.quit(); + }); + + test('Adding a costume', async () => { + await loadUri(uri); + await clickXpath('//button[@title="tryit"]'); + await clickText('Costumes'); + await clickText('Add Costume'); + const el = await findByXpath("//input[@placeholder='what are you looking for?']"); + await el.sendKeys('abb'); + await clickText('Abby-a'); // Should close the modal, then click the costumes in the selector + await findByXpath("//input[@value='Abby-a']"); // Should show editor for new costume + const logs = await getLogs(); + await expect(logs).toEqual([]); + }); + + test('Adding a backdrop', async () => { + await loadUri(uri); + await clickXpath('//button[@title="tryit"]'); + await clickText('Add Backdrop'); + const el = await findByXpath("//input[@placeholder='what are you looking for?']"); + await el.sendKeys('blue'); + await clickText('Blue Sky'); // Should close the modal + const logs = await getLogs(); + await expect(logs).toEqual([]); + }); +}); diff --git a/test/integration/examples.test.js b/test/integration/examples.test.js index 1bf2c0f5ba539269ff7889b6d032b478be538d60..f745dc24d2c0101582e5901d581d7dd901f717d7 100644 --- a/test/integration/examples.test.js +++ b/test/integration/examples.test.js @@ -13,10 +13,6 @@ const { loadUri } = new SeleniumHelper(); -const errorWhitelist = [ - 'The play() request was interrupted by a call to pause()' -]; - let driver; describe('player example', () => { @@ -37,7 +33,7 @@ describe('player example', () => { await clickXpath('//img[@title="Go"]'); await new Promise(resolve => setTimeout(resolve, 2000)); await clickXpath('//img[@title="Stop"]'); - const logs = await getLogs(errorWhitelist); + const logs = await getLogs(); await expect(logs).toEqual([]); }); }); @@ -60,7 +56,7 @@ describe('blocks example', () => { await clickXpath('//img[@title="Go"]'); await new Promise(resolve => setTimeout(resolve, 2000)); await clickXpath('//img[@title="Stop"]'); - const logs = await getLogs(errorWhitelist); + const logs = await getLogs(); await expect(logs).toEqual([]); }); @@ -82,7 +78,7 @@ describe('blocks example', () => { el = await findByXpath("//input[@placeholder='']"); await el.sendKeys('second variable'); await clickButton('OK'); - const logs = await getLogs(errorWhitelist); + const logs = await getLogs(); await expect(logs).toEqual([]); }); }); diff --git a/test/integration/localization.test.js b/test/integration/localization.test.js new file mode 100644 index 0000000000000000000000000000000000000000..b99066a3541211ae27fac253396a31a6d206951e --- /dev/null +++ b/test/integration/localization.test.js @@ -0,0 +1,49 @@ +import path from 'path'; +import SeleniumHelper from '../helpers/selenium-helper'; + +const { + clickText, + clickXpath, + findByText, + getDriver, + getLogs, + loadUri, + scope +} = new SeleniumHelper(); + +const uri = path.resolve(__dirname, '../../build/index.html'); + +let driver; + +describe('Localization', () => { + beforeAll(() => { + driver = getDriver(); + }); + + afterAll(async () => { + await driver.quit(); + }); + + // Skipped temporarily while the language selector is marked as + // "Coming Soon" + test.skip('Localization', async () => { + await loadUri(uri); + await clickXpath('//button[@title="tryit"]'); + await clickText('Blocks'); + await clickText('Extensions'); + await clickText('Pen', scope.modal); // Modal closes + await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for scroll animation + await clickText('English'); + await clickText('Deutsch'); + await new Promise(resolve => setTimeout(resolve, 1000)); // wait for blocks refresh + await clickText('Pen'); // will need to be updated when 'Pen' is translated + + // Make sure "Add Sprite" has changed to "Figur hinzufügen" + await findByText('Figur hinzufügen'); + // Find the stamp block in German + await findByText('Abdruck'); + + const logs = await getLogs(); + await expect(logs).toEqual([]); + }); +}); diff --git a/test/integration/project-loading.test.js b/test/integration/project-loading.test.js new file mode 100644 index 0000000000000000000000000000000000000000..3bc4ecde03dde48b261da3fc1e9f816db8e1f6e2 --- /dev/null +++ b/test/integration/project-loading.test.js @@ -0,0 +1,60 @@ +import path from 'path'; +import SeleniumHelper from '../helpers/selenium-helper'; + +const { + clickXpath, + getDriver, + getLogs, + loadUri +} = new SeleniumHelper(); + +const uri = path.resolve(__dirname, '../../build/index.html'); + +let driver; + +describe('Loading projects by ID', () => { + beforeAll(() => { + driver = getDriver(); + }); + + afterAll(async () => { + await driver.quit(); + }); + + test('Load a project by ID', async () => { + const projectId = '96708228'; + await loadUri(`${uri}#${projectId}`); + await clickXpath('//button[@title="tryit"]'); + await new Promise(resolve => setTimeout(resolve, 2000)); + await clickXpath('//img[@title="Go"]'); + await new Promise(resolve => setTimeout(resolve, 2000)); + await clickXpath('//img[@title="Stop"]'); + const logs = await getLogs(); + await expect(logs).toEqual([]); + }); + + test('Load a project by ID (fullscreen)', async () => { + const prevSize = driver.manage() + .window() + .getSize(); + await new Promise(resolve => setTimeout(resolve, 2000)); + driver.manage() + .window() + .setSize(1920, 1080); + const projectId = '96708228'; + await loadUri(`${uri}#${projectId}`); + await clickXpath('//button[@title="tryit"]'); + await new Promise(resolve => setTimeout(resolve, 2000)); + await clickXpath('//img[@title="Full Screen Control"]'); + await clickXpath('//img[@title="Go"]'); + await new Promise(resolve => setTimeout(resolve, 2000)); + await clickXpath('//img[@title="Stop"]'); + prevSize.then(value => { + driver.manage() + .window() + .setSize(value.width, value.height); + }); + const logs = await getLogs(); + await expect(logs).toEqual([]); + }); +}); diff --git a/test/integration/sounds.test.js b/test/integration/sounds.test.js new file mode 100644 index 0000000000000000000000000000000000000000..475d2271907b234f5a595c53eca43b74b7d5fcbd --- /dev/null +++ b/test/integration/sounds.test.js @@ -0,0 +1,89 @@ +import path from 'path'; +import SeleniumHelper from '../helpers/selenium-helper'; + +const { + clickText, + clickXpath, + findByXpath, + getDriver, + getLogs, + loadUri, + rightClickText, + scope +} = new SeleniumHelper(); + +const uri = path.resolve(__dirname, '../../build/index.html'); + +let driver; + +describe('Working with sounds', () => { + beforeAll(() => { + driver = getDriver(); + }); + + afterAll(async () => { + await driver.quit(); + }); + + test('Adding a sound', async () => { + await loadUri(uri); + await clickXpath('//button[@title="tryit"]'); + await clickText('Sounds'); + + // Delete the sound + await rightClickText('Meow', scope.soundsTab); + await clickText('delete', scope.soundsTab); + await driver.switchTo().alert() + .accept(); + + // Add it back + await clickText('Add Sound'); + let el = await findByXpath("//input[@placeholder='what are you looking for?']"); + await el.sendKeys('meow'); + await clickText('Meow', scope.modal); // Should close the modal + + // Add a new sound + await clickText('Add Sound'); + 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 findByXpath("//input[@value='Chomp']"); // Should show editor for new sound + + await clickXpath('//button[@title="Play"]'); + + await clickText('Louder'); + await clickText('Softer'); + await clickText('Faster'); + await clickText('Slower'); + await clickText('Robot'); + await clickText('Echo'); + await clickText('Reverse'); + + const logs = await getLogs(); + await expect(logs).toEqual([]); + }); + + // Regression test for gui issue #1320 + test('Switching sprites with different numbers of sounds', async () => { + await loadUri(uri); + await clickXpath('//button[@title="tryit"]'); + + // Add a sound so this sprite has 2 sounds. + await clickText('Sounds'); + await clickText('Add Sound'); + await clickText('A Bass'); // Closes the modal + + // Now add a sprite with only one sound. + await clickText('Add Sprite'); + await clickText('Abby'); // Doing this used to crash the editor. + + await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for error + + // Make sure the 'Oops' screen is not visible + const content = await driver.getPageSource(); + expect(content.indexOf('Oops')).toEqual(-1); + + const logs = await getLogs(); + await expect(logs).toEqual([]); + }); +}); diff --git a/test/integration/sprites.test.js b/test/integration/sprites.test.js new file mode 100644 index 0000000000000000000000000000000000000000..5e02623ee3ec026d18a26de2f784d16e24d87ee4 --- /dev/null +++ b/test/integration/sprites.test.js @@ -0,0 +1,41 @@ +import path from 'path'; +import SeleniumHelper from '../helpers/selenium-helper'; + +const { + clickText, + clickXpath, + findByText, + getDriver, + getLogs, + loadUri, + rightClickText, + scope +} = new SeleniumHelper(); + +const uri = path.resolve(__dirname, '../../build/index.html'); + +let driver; + +describe('Working with sprites', () => { + beforeAll(() => { + driver = getDriver(); + }); + + afterAll(async () => { + await driver.quit(); + }); + + test('Deleting only sprite does not crash', async () => { + await loadUri(uri); + await clickXpath('//button[@title="tryit"]'); + await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for scroll animation + await rightClickText('Sprite1', scope.spriteTile); + await clickText('delete', scope.spriteTile); + await driver.switchTo().alert() + .accept(); + // Confirm that the stage has been switched to + await findByText('Stage selected: no motion blocks'); + const logs = await getLogs(); + await expect(logs).toEqual([]); + }); +}); diff --git a/test/integration/test.js b/test/integration/test.js deleted file mode 100644 index 7fa5cadb6e0161b16545f2c334f34d20a995322e..0000000000000000000000000000000000000000 --- a/test/integration/test.js +++ /dev/null @@ -1,299 +0,0 @@ -import path from 'path'; -import SeleniumHelper from '../helpers/selenium-helper'; - -const { - clickText, - clickButton, - clickXpath, - findByText, - findByXpath, - getDriver, - getLogs, - loadUri, - rightClickText -} = new SeleniumHelper(); - -const uri = path.resolve(__dirname, '../../build/index.html'); - -const errorWhitelist = [ - 'The play() request was interrupted by a call to pause()' -]; - -let driver; - -const blocksTabScope = "*[@id='react-tabs-1']"; -const soundsTabScope = "*[@id='react-tabs-5']"; -const reportedValueScope = '*[@class="blocklyDropDownContent"]'; -const modalScope = '*[@class="ReactModalPortal"]'; - -describe('costumes, sounds and variables', () => { - beforeAll(() => { - driver = getDriver(); - }); - - afterAll(async () => { - await driver.quit(); - }); - - test('Blocks report when clicked in the toolbox', async () => { - await loadUri(uri); - await clickXpath('//button[@title="tryit"]'); - await clickText('Blocks'); - await clickText('Operators', blocksTabScope); - await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for scroll animation - await clickText('join', blocksTabScope); // Click "join <hello> <world>" block - await findByText('helloworld', reportedValueScope); // Tooltip with result - const logs = await getLogs(errorWhitelist); - await expect(logs).toEqual([]); - }); - - test('Switching sprites updates the block menus', async () => { - await loadUri(uri); - await clickXpath('//button[@title="tryit"]'); - await clickText('Sound', blocksTabScope); - await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for scroll animation - // "Meow" sound block should be visible - await findByText('Meow', blocksTabScope); - await clickText('Backdrops'); // Switch to the backdrop - // Now "pop" sound block should be visible and motion blocks hidden - await findByText('pop', blocksTabScope); - await clickText('Motion', blocksTabScope); - await findByText('Stage selected: no motion blocks'); - - const logs = await getLogs(errorWhitelist); - await expect(logs).toEqual([]); - }); - - test('Adding a costume', async () => { - await loadUri(uri); - await clickXpath('//button[@title="tryit"]'); - await clickText('Costumes'); - await clickText('Add Costume'); - const el = await findByXpath("//input[@placeholder='what are you looking for?']"); - await el.sendKeys('abb'); - await clickText('Abby-a'); // Should close the modal, then click the costumes in the selector - await findByXpath("//input[@value='Abby-a']"); // Should show editor for new costume - const logs = await getLogs(errorWhitelist); - await expect(logs).toEqual([]); - }); - - test('Adding a backdrop', async () => { - await loadUri(uri); - await clickXpath('//button[@title="tryit"]'); - await clickText('Add Backdrop'); - const el = await findByXpath("//input[@placeholder='what are you looking for?']"); - await el.sendKeys('blue'); - await clickText('Blue Sky'); // Should close the modal - const logs = await getLogs(errorWhitelist); - await expect(logs).toEqual([]); - }); - - test('Adding a sound', async () => { - await loadUri(uri); - await clickXpath('//button[@title="tryit"]'); - await clickText('Sounds'); - - // Delete the sound - await rightClickText('Meow', soundsTabScope); - await clickText('delete', soundsTabScope); - await driver.switchTo().alert() - .accept(); - - // Add it back - await clickText('Add Sound'); - let el = await findByXpath("//input[@placeholder='what are you looking for?']"); - await el.sendKeys('meow'); - await clickText('Meow', modalScope); // Should close the modal - - // Add a new sound - await clickText('Add Sound'); - 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 findByXpath("//input[@value='Chomp']"); // Should show editor for new sound - - await clickXpath('//button[@title="Play"]'); - - await clickText('Louder'); - await clickText('Softer'); - await clickText('Faster'); - await clickText('Slower'); - await clickText('Robot'); - await clickText('Echo'); - await clickText('Reverse'); - - const logs = await getLogs(errorWhitelist); - await expect(logs).toEqual([]); - }); - - test('Load a project by ID', async () => { - const projectId = '96708228'; - await loadUri(`${uri}#${projectId}`); - await new Promise(resolve => setTimeout(resolve, 2000)); - await clickXpath('//img[@title="Go"]'); - await new Promise(resolve => setTimeout(resolve, 2000)); - await clickXpath('//img[@title="Stop"]'); - const logs = await getLogs(errorWhitelist); - await expect(logs).toEqual([]); - }); - - test('Load a project by ID (fullscreen)', async () => { - const prevSize = driver.manage() - .window() - .getSize(); - await new Promise(resolve => setTimeout(resolve, 2000)); - driver.manage() - .window() - .setSize(1920, 1080); - const projectId = '96708228'; - await loadUri(`${uri}#${projectId}`); - await clickXpath('//button[@title="tryit"]'); - await new Promise(resolve => setTimeout(resolve, 2000)); - await clickXpath('//img[@title="Full Screen Control"]'); - await clickXpath('//img[@title="Go"]'); - await new Promise(resolve => setTimeout(resolve, 2000)); - await clickXpath('//img[@title="Stop"]'); - prevSize.then(value => { - driver.manage() - .window() - .setSize(value.width, value.height); - }); - const logs = await getLogs(errorWhitelist); - await expect(logs).toEqual([]); - }); - - test('Creating variables', async () => { - await loadUri(uri); - await clickXpath('//button[@title="tryit"]'); - await clickText('Blocks'); - await clickText('Variables', blocksTabScope); - await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for scroll animation - - // Expect a default variable "my variable" to be visible - await clickText('my\u00A0variable', blocksTabScope); - await findByText('0', reportedValueScope); - - await clickText('Make a Variable'); - let el = await findByXpath("//input[@placeholder='']"); - await el.sendKeys('score'); - await clickButton('OK'); - await clickText('Make a Variable'); - el = await findByXpath("//input[@placeholder='']"); - await el.sendKeys('second variable'); - await clickButton('OK'); - - // Make sure reporting works on a new variable - await clickText('Variables', blocksTabScope); - await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for scroll animation - await clickText('score', blocksTabScope); - await findByText('0', reportedValueScope); // Tooltip with result - - const logs = await getLogs(errorWhitelist); - await expect(logs).toEqual([]); - }); - - test('Importing extensions', async () => { - await loadUri(uri); - await clickXpath('//button[@title="tryit"]'); - await clickText('Blocks'); - await clickText('Extensions'); - await clickText('Pen', modalScope); // Modal closes - await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for scroll animation - await clickText('stamp', blocksTabScope); // Click the "stamp" block - - // Make sure trying to load the extension again scrolls back down - await clickText('Motion', blocksTabScope); // To scroll the list back to the top - await clickText('Extensions'); - await clickText('Pen', modalScope); // Modal closes - await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for scroll animation - await clickText('stamp', blocksTabScope); // Would fail if didn't scroll back - - // Make sure switching sprites doesn't clear extensions - await clickText('Backdrops'); // Switch to the backdrop - await findByText('Pen', blocksTabScope); // Pen extension should still be loaded - - const logs = await getLogs(errorWhitelist); - await expect(logs).toEqual([]); - }); - - test('Deleting only sprite does not crash', async () => { - const spriteTileContext = '*[starts-with(@class,"react-contextmenu-wrapper")]'; - await loadUri(uri); - await clickXpath('//button[@title="tryit"]'); - await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for scroll animation - await rightClickText('Sprite1', spriteTileContext); - await clickText('delete', spriteTileContext); - await driver.switchTo().alert() - .accept(); - // Confirm that the stage has been switched to - await findByText('Stage selected: no motion blocks'); - const logs = await getLogs(errorWhitelist); - await expect(logs).toEqual([]); - }); - - test('Custom procedures', async () => { - await loadUri(uri); - await clickXpath('//button[@title="tryit"]'); - await clickText('My Blocks'); - await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for scroll animation - await clickText('Make a Block'); - // Click on the "add an input" buttons - await clickText('number or text', modalScope); - await clickText('boolean', modalScope); - await clickText('Add a label', modalScope); - await clickText('OK', modalScope); - - // Make sure a "define" block has been added to the workspace - await findByText('define', blocksTabScope); - - const logs = await getLogs(errorWhitelist); - await expect(logs).toEqual([]); - }); - - // Skipped temporarily while the language selector is marked as - // "Coming Soon" - test.skip('Localization', async () => { - await loadUri(uri); - await clickXpath('//button[@title="tryit"]'); - await clickText('Blocks'); - await clickText('Extensions'); - await clickText('Pen', modalScope); // Modal closes - await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for scroll animation - await clickText('English'); - await clickText('Deutsch'); - await new Promise(resolve => setTimeout(resolve, 1000)); // wait for blocks refresh - await clickText('Pen'); // will need to be updated when 'Pen' is translated - - // Make sure "Add Sprite" has changed to "Figur hinzufügen" - await findByText('Figur hinzufügen'); - // Find the stamp block in German - await findByText('Abdruck'); - - const logs = await getLogs(errorWhitelist); - await expect(logs).toEqual([]); - }); - - // Regression test for gui issue #1320 - test('Switching sprites with different numbers of sounds', async () => { - await loadUri(uri); - await clickXpath('//button[@title="tryit"]'); - - // Add a sound so this sprite has 2 sounds. - await clickText('Sounds'); - await clickText('Add Sound'); - await clickText('A Bass'); // Closes the modal - - // Now add a sprite with only one sound. - await clickText('Add Sprite'); - await clickText('Abby'); // Doing this used to crash the editor. - - await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for error - - // Make sure the 'Oops' screen is not visible - const content = await driver.getPageSource(); - expect(content.indexOf('Oops')).toEqual(-1); - - const logs = await getLogs(errorWhitelist); - await expect(logs).toEqual([]); - }); -});