165 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
		
		
			
		
	
	
			165 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Copyright (c) Microsoft Corporation.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Licensed under the Apache License, Version 2.0 (the "License");
							 | 
						||
| 
								 | 
							
								 * you may not use this file except in compliance with the License.
							 | 
						||
| 
								 | 
							
								 * You may obtain a copy of the License at
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *     http://www.apache.org/licenses/LICENSE-2.0
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Unless required by applicable law or agreed to in writing, software
							 | 
						||
| 
								 | 
							
								 * distributed under the License is distributed on an "AS IS" BASIS,
							 | 
						||
| 
								 | 
							
								 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
							 | 
						||
| 
								 | 
							
								 * See the License for the specific language governing permissions and
							 | 
						||
| 
								 | 
							
								 * limitations under the License.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// The script does basic transformation of .spec.ts code to .java unit tests.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const path = require('path');
							 | 
						||
| 
								 | 
							
								const fs = require('fs');
							 | 
						||
| 
								 | 
							
								const os = require('os');
							 | 
						||
| 
								 | 
							
								const util = require('util');
							 | 
						||
| 
								 | 
							
								const { argv } = require('process');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(async () => {
							 | 
						||
| 
								 | 
							
								  if (process.argv.length < 3) throw new Error("Usage: node to_java.js <test>.spec.js");
							 | 
						||
| 
								 | 
							
								  const file = argv[2];
							 | 
						||
| 
								 | 
							
								  if (!file.endsWith('.spec.ts')) throw new Error("Unexpected input: " + file);
							 | 
						||
| 
								 | 
							
								  console.log('Reading: ' + file);
							 | 
						||
| 
								 | 
							
								  let content = await util.promisify(fs.readFile)(file);
							 | 
						||
| 
								 | 
							
								  content = content.toString();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function toCamelCase(match, p1, offset, string) {
							 | 
						||
| 
								 | 
							
								    return p1.toUpperCase();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function itReplacer(match, p1, p2, p3, offset, string) {
							 | 
						||
| 
								 | 
							
								    // let name = p1.replace(/[ :'\-=\[\]\<\>]/g, '_');
							 | 
						||
| 
								 | 
							
								    let name = p1.replace(/\W+(.)/g, toCamelCase);
							 | 
						||
| 
								 | 
							
								    // Remove special chars from the end.
							 | 
						||
| 
								 | 
							
								    name = name.replace(/\W+$/, '');
							 | 
						||
| 
								 | 
							
								    // console.log(name);
							 | 
						||
| 
								 | 
							
								    return `@Test
							 | 
						||
| 
								 | 
							
								void ${name}() {`;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  content = content.replace(/playwrightTest\('(.+)',.*{/g, itReplacer);
							 | 
						||
| 
								 | 
							
								  content = content.replace(/browserTest\('(.+)',.*{/g, itReplacer);
							 | 
						||
| 
								 | 
							
								  content = content.replace(/pageTest\('(.+)',.*{/g, itReplacer);
							 | 
						||
| 
								 | 
							
								  content = content.replace(/test\('(.+)',.*{/g, itReplacer);
							 | 
						||
| 
								 | 
							
								  content = content.replace(/it\('(.+)',.*{/g, itReplacer);
							 | 
						||
| 
								 | 
							
								  content = content.replace(/it\(`(.+)`,.*{/g, itReplacer);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Test's closing bracket: });
							 | 
						||
| 
								 | 
							
								  content = content.replace(/\n\}\);/g, '\n}');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  content = content.replace(/ async route => {/g, ' (route, request) -> {');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/ route => {/g, ' (route, request) -> {');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/ async \(route, request\) => {/g, ' (route, request) -> {');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/ \(route, request\) => {/g, ' (route, request) -> {');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/(server.setRoute.+)\(req, res\) => \{/g, '$1exchange -> {');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  content = content.replace(/([^\\])"/g, '$1SINGLE_QUOTE');
							 | 
						||
| 
								 | 
							
								  // content = content.replace(/(\) \=\>.*)'/g, '$1 XXX');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Replace single quotes with double quotes
							 | 
						||
| 
								 | 
							
								  content = content.replace(/''/g, '""');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/(?<!\) \=\>.*)([^\\])'/g, '$1"');
							 | 
						||
| 
								 | 
							
								  // Replace double quotes with single quotes
							 | 
						||
| 
								 | 
							
								  content = content.replace(/SINGLE_QUOTE/g, "'");
							 | 
						||
| 
								 | 
							
								  content = content.replace(/`/g, '"');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // quote lambdas
							 | 
						||
| 
								 | 
							
								  content = content.replace(/request => requests.push\(request\)/g, 'request -> requests.add(request)');
							 | 
						||
| 
								 | 
							
								  // content = content.replace(/, ([^,\(]+ \=\> [^\)]+)\)/g, ', "$1")');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/page.evaluate\((\(\) => [^\)]+)\)/g, 'page.evaluate("$1")');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Remove await/Promise.all
							 | 
						||
| 
								 | 
							
								  // Match all [^;] inside Promise.all([...]); to overcome greedy match and not include next foo([...]) calls.
							 | 
						||
| 
								 | 
							
								  content = content.replace(/const \[(.+)\] = await Promise.all\(\[([^;]+|)\]\);/g, '$1 = $2');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/await Promise.all\(\[([^;]+|)\]\);/g, '$1');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/Promise\.all\(\[/g, '');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/await /g, '');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Rename some methods
							 | 
						||
| 
								 | 
							
								  content = content.replace(/context\.tracing/g, 'context.tracing()');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/\.goto\(/g, '.navigate(');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/\.continue\(/g, '.resume(');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/\.\$eval\(/g, '.evalOnSelector(');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/\.\$\$eval\(/g, '.evalOnSelectorAll(');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/\.\$\(/g, '.querySelector(');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/\.\$\$\(/g, '.querySelectorAll(');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  content = content.replace(/\.keyboard\./g, '.keyboard().');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/\.mouse\./g, '.mouse().');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/\.coverage\./g, '.coverage().');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/\.accessibility\./g, '.accessibility().');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/\.length/g, '.size()');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  content = content.replace(/expect\((.+)\).toBeTruthy\(\);/g, 'assertNotNull($1);');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/expect\(error.message\)\.toContain\((.+)\);/g, 'assertTrue(e.getMessage().contains($1), e.getMessage());');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/expect\((.+)\)\.toContain\((.+)\);/g, 'assertTrue($1.contains($2));');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/expect\((.+)\)\.toBe\(null\);/g, 'assertNull($1);');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/expect\((.+)\)\.not.toBe\(null\);/g, 'assertNotNull($1);');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/expect\((.+\.evaluate.+)\)\.toBe\(true\);/g, 'assertEquals(true, $1);');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/expect\((.+)\)\.toBe\(true\);/g, 'assertTrue($1);');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/expect\((.+)\)\.toBe\((.+)\);/g, 'assertEquals($2, $1);');
							 | 
						||
| 
								 | 
							
								  // Match all [^;] inside .toEqual([...]); to overcome greedy match and not include next foo([...]) calls.
							 | 
						||
| 
								 | 
							
								  content = content.replace(/expect\((.+)\)\.toEqual\(\[([^;]+|)\]\);/g, 'assertEquals(asList($2), $1);');
							 | 
						||
| 
								 | 
							
								  for (let before = null; before !== content;) {
							 | 
						||
| 
								 | 
							
								    before = content;
							 | 
						||
| 
								 | 
							
								    content = content.replace(/(asList\([^\)\']*)'/g, '$1"');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  content = content.replace(/expect\((.+)\)\.toEqual\((.+)\);/g, 'assertEquals($2, $1);');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  content = content.replace(/(?<!.files)\[(\d+)\]/g, '.get($1)');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/\[("[^"]+")\]/g, '.get($1)');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/.push\(/g, '.add(');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Define common types
							 | 
						||
| 
								 | 
							
								  content = content.replace(/const request = playwright.request.newContext/g, 'APIRequestContext request = playwright.request.newContext');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/const (browser[^\s=]*) = /g, 'Browser $1 = ');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/const sizes = /g, 'Sizes sizes = ');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/const remote = /g, 'Browser remote = ');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/const context = /g, 'BrowserContext context = ');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/const (page[^\s=]*) = /g, 'Page $1 = ');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/const newPage = /g, 'Page newPage = ');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/const button/g, 'ElementHandle button');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/const result = /g, 'Object result = ');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/const response = /g, 'Response response = ');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/const request = /g, 'Request request = ');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/const requests = \[\];/g, 'List<Request> requests = new ArrayList<>();');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/const snapshot = page.accessibility/g, 'AccessibilityNode snapshot = page.accessibility');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/snapshot\.children\./g, 'snapshot.children().');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/const (.+) = \[\];/g, 'List<> $1 = new ArrayList<>();');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/const (\w+ = .+evalOnSelector)/g, 'Object $1');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/const (\w+ = .+querySelector)/g, 'ElementHandle $1');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/const messages = \[\]/g, 'List<String> messages = new ArrayList<>()');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/const frame = /g, 'Frame frame = ');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/const elementHandle = (.+)/g, 'JSHandle jsHandle = $1\n  ElementHandle elementHandle = jsHandle.asElement();\n  assertNotNull(elementHandle);');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/const (\w+ = \w+\.boundingBox)/g, 'ElementHandle.BoundingBox $1');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/assertEquals\({ x: (\d+), y: (\d+), width: (\d+), height: (\d+) }, box\);/g, `assertEquals(box.x, $1);
							 | 
						||
| 
								 | 
							
								  assertEquals(box.y, $2);
							 | 
						||
| 
								 | 
							
								  assertEquals(box.width, $3);
							 | 
						||
| 
								 | 
							
								  assertEquals(box.height, $4);`);
							 | 
						||
| 
								 | 
							
								  content = content.replace(/setViewportSize\({ width: (\d+), height: (\d+) }\)/g, 'setViewportSize($1, $2)');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/\.on\("([^"]+)", /g, (match, p1, offset, string) => `\.on${toTitleCase(p1)}(`);
							 | 
						||
| 
								 | 
							
								  content = content.replace(/page.waitForEvent\("([^"]+)"/g, (match, p1, offset, string) => `page.waitFor${toTitleCase(p1)}(`);
							 | 
						||
| 
								 | 
							
								  content = content.replace(/server.waitForRequest/g, 'server.futureRequest');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/context.request/g, 'context.request()');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/page.request/g, 'page.request()');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/playwright.request/g, 'playwright.request()');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // try/catch
							 | 
						||
| 
								 | 
							
								  content = content.replace(/const error = /g, 'try {\n');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/\.catch\(e => e\)[;,]/g, ';\nfail("did not throw");\n} catch (PlaywrightException e) {}\n');
							 | 
						||
| 
								 | 
							
								  content = content.replace(/(.+)\.catch\(e => error = e\);/g, '  try {\n  $1;\n    fail("did not throw");\n  } catch (PlaywrightException e) {\n  }\n');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const output = file.replace(/\.spec\.ts$/, ".java")
							 | 
						||
| 
								 | 
							
								  console.log('Writing: ' + output);
							 | 
						||
| 
								 | 
							
								  await util.promisify(fs.writeFile)(output, content)
							 | 
						||
| 
								 | 
							
								})();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function toTitleCase(s) {
							 | 
						||
| 
								 | 
							
								  return s[0].toUpperCase() + s.substr(1);
							 | 
						||
| 
								 | 
							
								}
							 |