chore: TypeScript to JavaScript + JSDoc for tests (#8526)

pull/8566/head
Yuichiro Yamashita 1 year ago committed by GitHub
parent 8ffd2112bc
commit 384927dbf3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,9 +1,12 @@
const is_unit_test = process.env.UNIT_TEST; const is_unit_test = process.env.UNIT_TEST;
module.exports = { module.exports = {
file: is_unit_test ? [] : ['test/test.ts'], file: is_unit_test ? [] : ['test/test.js'],
require: [ require: [
'sucrase/register' 'sucrase/register'
],
"node-option": [
"experimental-modules"
] ]
}; };

@ -16,7 +16,7 @@ const page = `
const assert = fs.readFileSync(`${__dirname}/assert.js`, 'utf-8'); const assert = fs.readFileSync(`${__dirname}/assert.js`, 'utf-8');
describe('custom-elements', function() { describe('custom-elements', function () {
// Note: Increase the timeout in preparation for restarting Chromium due to SIGSEGV. // Note: Increase the timeout in preparation for restarting Chromium due to SIGSEGV.
this.timeout(10000); this.timeout(10000);
let svelte; let svelte;
@ -81,6 +81,7 @@ describe('custom-elements', function() {
const bundle = await rollup({ const bundle = await rollup({
input: `${__dirname}/samples/${dir}/test.js`, input: `${__dirname}/samples/${dir}/test.js`,
plugins: [ plugins: [
// @ts-ignore -- TODO: fix this
{ {
resolveId(importee) { resolveId(importee) {
if (importee === 'svelte/internal' || importee === './internal') { if (importee === 'svelte/internal' || importee === './internal') {

@ -4,11 +4,15 @@ import glob from 'tiny-glob/sync';
import * as path from 'path'; import * as path from 'path';
import * as fs from 'fs'; import * as fs from 'fs';
import * as colors from 'kleur'; import * as colors from 'kleur';
export const assert = (assert$1 as unknown) as typeof assert$1 & { htmlEqual: (actual: string, expected: string, message?: string) => void, htmlEqualWithOptions: (actual: string, expected: string, options: { preserveComments?: boolean, withoutNormalizeHtml?: boolean }, message?: string) => void };
/**
* @type {typeof assert$1 & { htmlEqual: (actual: string, expected: string, message?: string) => void, htmlEqualWithOptions: (actual: string, expected: string, options: { preserveComments?: boolean, withoutNormalizeHtml?: boolean }, message?: string) => void }}
*/
export const assert = /** @type {any} */ (assert$1);
// for coverage purposes, we need to test source files, // for coverage purposes, we need to test source files,
// but for sanity purposes, we need to test dist files // but for sanity purposes, we need to test dist files
export function loadSvelte(test: boolean = false) { export function loadSvelte(test = false) {
process.env.TEST = test ? 'true' : ''; process.env.TEST = test ? 'true' : '';
const resolved = require.resolve('../compiler.js'); const resolved = require.resolve('../compiler.js');
@ -68,7 +72,7 @@ for (const key of Object.getOwnPropertyNames(global)) {
} }
// implement mock scroll // implement mock scroll
window.scrollTo = function(pageXOffset, pageYOffset) { window.scrollTo = function (pageXOffset, pageYOffset) {
window.pageXOffset = pageXOffset; window.pageXOffset = pageXOffset;
window.pageYOffset = pageYOffset; window.pageYOffset = pageYOffset;
}; };
@ -140,7 +144,14 @@ function cleanChildren(node) {
} }
} }
export function normalizeHtml(window, html, { removeDataSvelte = false, preserveComments = false }: { removeDataSvelte?: boolean, preserveComments?: boolean }) { /**
*
* @param {Window} window
* @param {string} html
* @param {{ removeDataSvelte?: boolean, preserveComments?: boolean }} param2
* @returns
*/
export function normalizeHtml(window, html, { removeDataSvelte = false, preserveComments = false }) {
try { try {
const node = window.document.createElement('div'); const node = window.document.createElement('div');
node.innerHTML = html node.innerHTML = html
@ -155,11 +166,18 @@ export function normalizeHtml(window, html, { removeDataSvelte = false, preserve
} }
} }
export function normalizeNewline(html: string) { /**
* @param {string} html
* @returns {string}
*/
export function normalizeNewline(html) {
return html.replace(/\r\n/g, '\n'); return html.replace(/\r\n/g, '\n');
} }
export function setupHtmlEqual(options: { removeDataSvelte?: boolean } = {}) { /**
* @param {{ removeDataSvelte?: boolean }} options
*/
export function setupHtmlEqual(options = {}) {
const window = env(); const window = env();
// eslint-disable-next-line no-import-assign // eslint-disable-next-line no-import-assign
@ -170,8 +188,15 @@ export function setupHtmlEqual(options: { removeDataSvelte?: boolean } = {}) {
message message
); );
}; };
// eslint-disable-next-line no-import-assign
assert.htmlEqualWithOptions = (actual: string, expected: string, { preserveComments, withoutNormalizeHtml }: { preserveComments?: boolean, withoutNormalizeHtml?: boolean }, message?: string) => { /**
*
* @param {string} actual
* @param {string} expected
* @param {{ preserveComments?: boolean, withoutNormalizeHtml?: boolean }} param2
* @param {string?} message
*/
assert.htmlEqualWithOptions = (actual, expected, { preserveComments, withoutNormalizeHtml }, message) => {
assert.deepEqual( assert.deepEqual(
withoutNormalizeHtml withoutNormalizeHtml
? normalizeNewline(actual).replace(/(\sdata-svelte-h="[^"]+")/g, options.removeDataSvelte ? '' : '$1') ? normalizeNewline(actual).replace(/(\sdata-svelte-h="[^"]+")/g, options.removeDataSvelte ? '' : '$1')
@ -252,7 +277,8 @@ const original_set_timeout = global.setTimeout;
export function useFakeTimers() { export function useFakeTimers() {
const callbacks = []; const callbacks = [];
global.setTimeout = function(fn) { // @ts-ignore
global.setTimeout = function (fn) {
callbacks.push(fn); callbacks.push(fn);
}; };
@ -289,7 +315,14 @@ export function prettyPrintPuppeteerAssertionError(message) {
} }
} }
export async function retryAsync<T>(fn: () => Promise<T>, maxAttempts: number = 3, interval: number = 1000): Promise<T> { /**
*
* @param {() => Promise<import ('puppeteer').Browser>} fn
* @param {number} maxAttempts
* @param {number} interval
* @returns {Promise<import ('puppeteer').Browser>}
*/
export async function retryAsync(fn, maxAttempts = 3, interval = 1000) {
let attempts = 0; let attempts = 0;
while (attempts <= maxAttempts) { while (attempts <= maxAttempts) {
try { try {
@ -301,8 +334,15 @@ export async function retryAsync<T>(fn: () => Promise<T>, maxAttempts: number =
} }
} }
// NOTE: Chromium may exit with SIGSEGV, so retry in that case /**
export async function executeBrowserTest<T>(browser, launchPuppeteer: () => Promise<T>, additionalAssertion: () => void, onError: (err: Error) => void) { * NOTE: Chromium may exit with SIGSEGV, so retry in that case
* @param {import ('puppeteer').Browser} browser
* @param {() => Promise<import ('puppeteer').Browser>} launchPuppeteer
* @param {() => void} additionalAssertion
* @param {(err: Error) => void} onError
* @returns {Promise<import ('puppeteer').Browser>}
*/
export async function executeBrowserTest(browser, launchPuppeteer, additionalAssertion, onError) {
let count = 0; let count = 0;
do { do {
count++; count++;
@ -310,6 +350,7 @@ export async function executeBrowserTest<T>(browser, launchPuppeteer: () => Prom
const page = await browser.newPage(); const page = await browser.newPage();
page.on('console', (type) => { page.on('console', (type) => {
// @ts-ignore -- TODO: Fix type
console[type._type](type._text); console[type._type](type._text);
}); });
@ -318,7 +359,10 @@ export async function executeBrowserTest<T>(browser, launchPuppeteer: () => Prom
console.error(error); console.error(error);
}); });
await page.goto('http://localhost:6789'); await page.goto('http://localhost:6789');
const result = await page.evaluate(() => test(document.querySelector('main'))); const result = await page.evaluate(() => {
// @ts-ignore -- It runs in browser context.
return test(document.querySelector('main'));
});
if (result) console.log(result); if (result) console.log(result);
additionalAssertion(); additionalAssertion();
await page.close(); await page.close();

@ -19,7 +19,7 @@ describe('hydration', () => {
before(() => { before(() => {
const svelte = loadSvelte(); const svelte = loadSvelte();
require.extensions['.svelte'] = function(module, filename) { require.extensions['.svelte'] = function (module, filename) {
const options = Object.assign( const options = Object.assign(
{ {
filename, filename,
@ -135,6 +135,6 @@ describe('hydration', () => {
} }
fs.readdirSync(`${__dirname}/samples`).forEach(dir => { fs.readdirSync(`${__dirname}/samples`).forEach(dir => {
runTest(dir, null); runTest(dir);
}); });
}); });

@ -67,7 +67,7 @@ describe('ssr', () => {
format: 'cjs' format: 'cjs'
}; };
require('../../register')(compileOptions); require('../../register.js')(compileOptions);
const Component = require(`${dir}/main.svelte`).default; const Component = require(`${dir}/main.svelte`).default;
@ -174,7 +174,7 @@ describe('ssr', () => {
glob('**/*.svelte', { cwd }).forEach(file => { glob('**/*.svelte', { cwd }).forEach(file => {
if (file[0] === '_') return; if (file[0] === '_') return;
const dir = `${cwd}/_output/ssr`; const dir = `${cwd}/_output/ssr`;
const out = `${dir}/${file.replace(/\.svelte$/, '.js')}`; const out = `${dir}/${file.replace(/\.svelte$/, '.js')}`;
if (fs.existsSync(out)) { if (fs.existsSync(out)) {
@ -208,12 +208,12 @@ describe('ssr', () => {
if (config.ssrHtml) { if (config.ssrHtml) {
assert.htmlEqualWithOptions(html, config.ssrHtml, { assert.htmlEqualWithOptions(html, config.ssrHtml, {
preserveComments: compileOptions.preserveComments, preserveComments: compileOptions.preserveComments,
withoutNormalizeHtml: config.withoutNormalizeHtml withoutNormalizeHtml: config.withoutNormalizeHtml
}); });
} else if (config.html) { } else if (config.html) {
assert.htmlEqualWithOptions(html, config.html, { assert.htmlEqualWithOptions(html, config.html, {
preserveComments: compileOptions.preserveComments, preserveComments: compileOptions.preserveComments,
withoutNormalizeHtml: config.withoutNormalizeHtml withoutNormalizeHtml: config.withoutNormalizeHtml
}); });
} }

@ -2,15 +2,17 @@ const fs = require('fs');
require('source-map-support').install(); require('source-map-support').install();
process.env.TEST = true; process.env.TEST = 'true';
require.extensions['.js'] = function(module, filename) { require.extensions['.js'] = function (module, filename) {
const exports = []; const exports = [];
let code = fs.readFileSync(filename, 'utf-8') let code = fs.readFileSync(filename, 'utf-8')
.replace(/^import \* as (\w+) from ['"]([^'"]+)['"];?/gm, 'var $1 = require("$2");') .replace(/^import \* as (\S+) from ['"]([^'"]+)['"];?/gm, 'var $1 = require("$2");')
.replace(/^import (\w+) from ['"]([^'"]+)['"];?/gm, 'var {default: $1} = require("$2");')
.replace(/^import {([^}]+)} from ['"](.+)['"];?/gm, 'var {$1} = require("$2");') .replace(/^import {([^}]+)} from ['"](.+)['"];?/gm, 'var {$1} = require("$2");')
.replace(/^import (\S+),\s+?{([^}]+)} from ['"](.+)['"];?/gm, 'var {default: $1, $2} = require("$3");')
.replace(/^import (\S+) from ['"]([./][^'"]+)['"];?/gm, 'var {default: $1} = require("$2");')
.replace(/^import (\S+) from ['"]([^'"]+)['"];?/gm, 'var $1 = require("$2");')
.replace(/^export default /gm, 'exports.default = ') .replace(/^export default /gm, 'exports.default = ')
.replace(/^export (const|let|var|class|function|async\s+function) (\w+)/gm, (match, type, name) => { .replace(/^export (const|let|var|class|function|async\s+function) (\w+)/gm, (match, type, name) => {
exports.push(name); exports.push(name);

@ -2,20 +2,19 @@ import * as assert from 'assert';
import { getLocator } from 'locate-character'; import { getLocator } from 'locate-character';
import MagicString, { Bundle } from 'magic-string'; import MagicString, { Bundle } from 'magic-string';
type AssertMappedParameters = { /**
code: string; * @typedef {{ code: string; filename?: string; input: string | ReturnType<typeof getLocator>; input_code?: string; preprocessed: any; }} AssertMappedParameters
filename?: string; */
input: string | ReturnType<typeof getLocator>;
input_code?: string;
preprocessed: any;
};
/**
* @param {AssertMappedParameters} param
*/
export function assert_mapped( export function assert_mapped(
{ code, filename, input, input_code, preprocessed }: AssertMappedParameters { code, filename, input, input_code, preprocessed }
) { ) {
const locate_input = typeof input === 'function' ? input : getLocator(input); const locate_input = typeof input === 'function' ? input : getLocator(input);
if (filename === undefined) filename = 'input.svelte'; if (filename === undefined) filename = 'input.svelte';
if (input_code === undefined) input_code = code; if (input_code === undefined) input_code = code;
const source_loc = locate_input(input_code); const source_loc = locate_input(input_code);
assert.notEqual( assert.notEqual(
@ -43,14 +42,15 @@ export function assert_mapped(
); );
} }
type AssertNotMappedParameters = { /**
code: string; * @typedef {{ code: string; filename?: string; preprocessed: any; }} AssertNotMappedParameters
filename?: string; */
preprocessed: any;
};
/**
* @param {AssertNotMappedParameters} param
*/
export function assert_not_mapped( export function assert_not_mapped(
{ code, filename, preprocessed }: AssertNotMappedParameters { code, filename, preprocessed }
) { ) {
if (filename === undefined) filename = 'input.svelte'; if (filename === undefined) filename = 'input.svelte';
@ -73,9 +73,14 @@ export function assert_not_mapped(
); );
} }
/**
* @param {string} code
* @param {ReturnType<typeof getLocator>} locate
* @param {string} filename
*/
export function assert_not_located( export function assert_not_located(
code: string, code,
locate: ReturnType<typeof getLocator>, locate,
filename = 'input.svelte' filename = 'input.svelte'
) { ) {
assert.equal( assert.equal(
@ -85,8 +90,14 @@ export function assert_not_located(
); );
} }
/**
* @param {Array<{ code: string | MagicString, filename: string }>} inputs
* @param {string} filename
* @param {string} separator
* @returns
*/
export function magic_string_bundle( export function magic_string_bundle(
inputs: Array<{ code: string | MagicString, filename: string }>, inputs,
filename = 'bundle.js', filename = 'bundle.js',
separator = '\n' separator = '\n'
) { ) {
@ -107,7 +118,12 @@ export function magic_string_bundle(
}; };
} }
export function magic_string_preprocessor_result(filename: string, src: MagicString) { /**
* @param {string} filename
* @param {MagicString} src
* @returns
*/
export function magic_string_preprocessor_result(filename, src) {
return { return {
code: src.toString(), code: src.toString(),
map: src.generateMap({ map: src.generateMap({
@ -118,7 +134,12 @@ export function magic_string_preprocessor_result(filename: string, src: MagicStr
}; };
} }
export function magic_string_replace_all(src: MagicString, search: string, replace: string) { /**
* @param {MagicString} src
* @param {string} search
* @param {string} replace
*/
export function magic_string_replace_all(src, search, replace) {
let idx = src.original.indexOf(search); let idx = src.original.indexOf(search);
if (idx == -1) throw new Error('search not found in src'); if (idx == -1) throw new Error('search not found in src');
do { do {

@ -101,6 +101,7 @@ describe('store', () => {
describe('readable', () => { describe('readable', () => {
it('creates a readable store', () => { it('creates a readable store', () => {
let running; let running;
/** @type {import('svelte/store').Subscriber<unknown>} */
let tick; let tick;
const store = readable(undefined, set => { const store = readable(undefined, set => {
@ -163,11 +164,12 @@ describe('store', () => {
}); });
}); });
/** @type {any} */
const fake_observable = { const fake_observable = {
subscribe(fn) { subscribe(fn) {
fn(42); fn(42);
return { return {
unsubscribe: () => {} unsubscribe: () => { }
}; };
} }
}; };
@ -290,7 +292,7 @@ describe('store', () => {
}); });
it('derived dependency does not update and shared ancestor updates', () => { it('derived dependency does not update and shared ancestor updates', () => {
const root = writable({ a: 0, b:0 }); const root = writable({ a: 0, b: 0 });
const values = []; const values = [];
const a = derived(root, $root => { const a = derived(root, $root => {
@ -451,6 +453,7 @@ describe('store', () => {
assert.equal(get(readableStore), 2); assert.equal(get(readableStore), 2);
assert.equal(get(readableStore), get(writableStore)); assert.equal(get(readableStore), get(writableStore));
// @ts-ignore
assert.throws(() => readableStore.set(3)); assert.throws(() => readableStore.set(3));
}); });

@ -1,14 +1,14 @@
const glob = require('tiny-glob/sync.js'); const glob = require('tiny-glob/sync.js');
require('./setup'); require('./setup.js');
// bind internal to jsdom // bind internal to jsdom
require('./helpers.ts'); require('./helpers.js');
require('../internal'); require('../internal');
console.clear(); console.clear();
const test_folders = glob('*/index.ts', { cwd: 'test' }); const test_folders = glob('*/index.js', { cwd: 'test' });
const solo_folders = test_folders.filter(folder => /\.solo/.test(folder)); const solo_folders = test_folders.filter(folder => /\.solo/.test(folder));
if (solo_folders.length) { if (solo_folders.length) {
Loading…
Cancel
Save