// These tests do not sign in with a user // Adding tests that sign in with user #6 // some tests use projects owned by user #2 const SeleniumHelper = require('./selenium-helpers.js'); const {until} = require('selenium-webdriver'); import path from 'path'; const { buildDriver, clickText, clickXpath, findText, findByXpath, isSignedIn, signIn, navigate, waitUntilVisible } = new SeleniumHelper(); const rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; // project IDs and URLs const unownedSharedId = process.env.UNOWNED_SHARED_PROJECT_ID || 1300006196; const unownedSharedUrl = `${rootUrl}/projects/${unownedSharedId}`; const ownedSharedId = process.env.OWNED_SHARED_PROJECT_ID || 1300009464; const ownedSharedUrl = `${rootUrl}/projects/${ownedSharedId}`; const ownedUnsharedID = process.env.OWNED_UNSHARED_PROJECT_ID || 1300009465; const ownedUnsharedUrl = `${rootUrl}/projects/${ownedUnsharedID}`; const unownedUnsharedID = process.env.UNOWNED_UNSHARED_PROJECT_ID || 1300006306; const unownedUnsharedUrl = `${rootUrl}/projects/${unownedUnsharedID}`; const unownedSharedScratch2ID = process.env.UNOWNED_SHARED_SCRATCH2_PROJECT_ID || 1300009487; const unownedSharedScratch2Url = `${rootUrl}/projects/${unownedSharedScratch2ID}`; const ownedUnsharedScratch2ID = process.env.OWNED_UNSHARED_SCRATCH2_PROJECT_ID || 1300009488; const ownedUnsharedScratch2Url = `${rootUrl}/projects/${ownedUnsharedScratch2ID}`; const username = `${process.env.SMOKE_USERNAME}6`; const password = process.env.SMOKE_PASSWORD; const remote = process.env.SMOKE_REMOTE || false; const FILE_MENU_XPATH = '//div[contains(@class, "menu-bar_menu-bar-item")]' + '[*[contains(@class, "menu-bar_collapsible-label")]//*[text()="File"]]'; jest.setTimeout(60000); let driver; describe('www-integration project-page signed out', () => { beforeAll(async () => { // expect(projectUrl).toBe(defined); driver = await buildDriver('www-integration project-page signed out'); await navigate(rootUrl); }); beforeEach(async () => { await navigate(unownedSharedUrl); const gfOverlay = await findByXpath('//div[@class="stage-wrapper_stage-wrapper_2bejr box_box_2jjDp"]'); await waitUntilVisible(gfOverlay, driver); }); afterAll(() => driver.quit()); // LOGGED OUT TESTS test('Find fullscreen button', async () => { await clickXpath('//div[starts-with(@class, "stage_green-flag-overlay")]'); await clickXpath('//img[contains(@alt, "Enter full screen mode")]'); const fullscreenGui = await findByXpath('//div[@class="guiPlayer fullscreen"]'); const guiVisible = await fullscreenGui.isDisplayed(); expect(guiVisible).toBe(true); }); test.skip('Open Copy Link modal', async () => { await clickXpath('//button[@class="button action-button copy-link-button"]'); const projectLink = await findByXpath('//input[@name="link"]'); const linkValue = await projectLink.getAttribute('value'); expect(linkValue).toEqual(unownedSharedUrl); }); test('Click Username to go to profile page', async () => { await clickXpath('//div[@class="title"]/a'); const userContent = await findByXpath('//div[@class="user-content"]'); const contentVisible = await userContent.isDisplayed(); expect(contentVisible).toBe(true); }); test('click See Inside to go to the editor', async () => { await clickXpath('//button[@class="button button see-inside-button"]'); const infoArea = await findByXpath('//div[@class="sprite-info_sprite-info_3EyZh box_box_2jjDp"]'); const areaVisible = await infoArea.isDisplayed(); expect(areaVisible).toBe(true); }); test('click View All remixes takes you to remix page', async () => { await clickXpath('//div[@class="list-header-link"]'); const originalLink = await findByXpath('//h2/a'); const link = await originalLink.getAttribute('href'); expect(link).toEqual(`${rootUrl}/projects/${unownedSharedId}/`); }); // Load an unshared project while signed out, get error test('Load an ushared project you do not own (error)', async () => { await navigate(unownedUnsharedUrl); const unavailableImage = await findByXpath('//img[@class="not-available-image"]'); await waitUntilVisible(unavailableImage, driver); const unavailableVisible = await unavailableImage.isDisplayed(); expect(unavailableVisible).toBe(true); }); }); // Logged in tests describe('www-integration project-page signed in', () => { beforeAll(async () => { // expect(projectUrl).toBe(defined); driver = await buildDriver('www-integration project-page signed in'); }); beforeEach(async () => { // The browser may or may not retain cookies between tests, depending on configuration. await navigate(rootUrl); if (!await isSignedIn()) { await signIn(username, password); } }); afterAll(() => driver.quit()); // LOGGED in TESTS // Load a shared project you own test('Load a shared project you own', async () => { await navigate(ownedSharedUrl); const gfOverlay = await findByXpath('//div[@class="stage-wrapper_stage-wrapper_2bejr box_box_2jjDp"]'); await waitUntilVisible(gfOverlay, driver); const gfVisible = await gfOverlay.isDisplayed(); expect(gfVisible).toBe(true); }); // Load a shared project you don't own test('Load a shared project you do not own', async () => { await navigate(unownedSharedUrl); const gfOverlay = await findByXpath('//div[@class="stage-wrapper_stage-wrapper_2bejr box_box_2jjDp"]'); await waitUntilVisible(gfOverlay, driver); const gfVisible = await gfOverlay.isDisplayed(); expect(gfVisible).toBe(true); }); // Load an unshared project you own test('Load an unshared project you own', async () => { await navigate(ownedUnsharedUrl); const gfOverlay = await findByXpath('//div[@class="stage-wrapper_stage-wrapper_2bejr box_box_2jjDp"]'); await waitUntilVisible(gfOverlay, driver); const gfVisible = await gfOverlay.isDisplayed(); expect(gfVisible).toBe(true); }); // Load an unshared project you don't own, get error test('Load an ushared project you do not own (error)', async () => { await navigate(unownedUnsharedUrl); const unavailableImage = await findByXpath('//img[@class="not-available-image"]'); await waitUntilVisible(unavailableImage, driver); const unavailableVisible = await unavailableImage.isDisplayed(); expect(unavailableVisible).toBe(true); }); // Load a shared scratch 2 project you don't own test('Load a shared scratch 2 project you do not own', async () => { await navigate(unownedSharedScratch2Url); const gfOverlay = await findByXpath('//div[@class="stage-wrapper_stage-wrapper_2bejr box_box_2jjDp"]'); await waitUntilVisible(gfOverlay, driver); const gfVisible = await gfOverlay.isDisplayed(); expect(gfVisible).toBe(true); }); // Load an unshared scratch 2 project you own test('Load an unshared scratch 2 project you own', async () => { await navigate(ownedUnsharedScratch2Url); const gfOverlay = await findByXpath('//div[@class="stage-wrapper_stage-wrapper_2bejr box_box_2jjDp"]'); await waitUntilVisible(gfOverlay, driver); const gfVisible = await gfOverlay.isDisplayed(); expect(gfVisible).toBe(true); }); }); describe('www-integration project-creation signed in', () => { beforeAll(async () => { driver = await buildDriver('www-integration project-creation signed in'); // SauceLabs doesn't have access to the sb3 used in 'load project from file' test // https://support.saucelabs.com/hc/en-us/articles/115003685593-Uploading-Files-to-a-Sauce-Labs-Virtual-Machine-during-a-Test if (remote) { await navigate('https://github.com/scratchfoundation/scratch-www/blob/develop/test/fixtures/project1.sb3'); await clickXpath('//button[@data-testid="download-raw-button"]'); await driver.sleep(3000); } }); beforeEach(async () => { // The browser may or may not retain cookies between tests, depending on configuration. await navigate(rootUrl); if (!await isSignedIn()) { await signIn(username, password); } }); afterAll(() => driver.quit()); test('make a copy of a project', async () => { await navigate(`${ownedUnsharedUrl}/editor`); await clickXpath(FILE_MENU_XPATH); await clickText('Save as a copy'); const successAlert = await findText('Project saved as a copy.'); const alertVisible = await successAlert.isDisplayed(); expect(alertVisible).toBe(true); await driver.sleep(1000); const infoArea = await findByXpath('//div[@class="sprite-info_sprite-info_3EyZh box_box_2jjDp"]'); const areaVisible = await infoArea.isDisplayed(); expect(areaVisible).toBe(true); }); test('remix a project', async () => { await navigate(unownedSharedUrl); const gfOverlay = await findByXpath('//div[@class="stage-wrapper_stage-wrapper_2bejr box_box_2jjDp"]'); await waitUntilVisible(gfOverlay, driver); await clickXpath('//button[@class="button remix-button"]'); const successAlert = await findText('Project saved as a remix.'); const alertVisible = await successAlert.isDisplayed(); expect(alertVisible).toBe(true); await driver.sleep(1000); const infoArea = await findByXpath('//div[@class="sprite-info_sprite-info_3EyZh box_box_2jjDp"]'); const areaVisible = await infoArea.isDisplayed(); expect(areaVisible).toBe(true); }); test('load project from file', async () => { // if remote, projectPath is Saucelabs path to downloaded file const projectPath = remote ? '/Users/chef/Downloads/project1.sb3' : path.resolve(__dirname, '../fixtures/project1.sb3'); // create a new project so there's unsaved content to trigger an alert await clickXpath('//li[@class="link create"]'); // upload file await clickXpath(FILE_MENU_XPATH); await clickText('Load from your computer'); const input = await findByXpath('//input[@accept=".sb,.sb2,.sb3"]'); await input.sendKeys(projectPath); // accept alert await driver.wait(until.alertIsPresent()); const alert = await driver.switchTo().alert(); await alert.accept(); // check that project is loaded const spriteTile = await findText('project1-sprite'); const spriteTileVisible = await spriteTile.isDisplayed(); expect(spriteTileVisible).toBe(true); // check that gui is still there after some time has passed await driver.sleep(1000); const infoArea = await findByXpath('//div[@class="sprite-info_sprite-info_3EyZh box_box_2jjDp"]'); const areaVisible = await infoArea.isDisplayed(); expect(areaVisible).toBe(true); }); });