diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index def5ecffd..548c006ed 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,7 +16,7 @@ You will need [Deno](https://deno.land/) 1.13+. 2. Clone the repository to your local device. 3. Create a new branch `git checkout -b BRANCH_NAME`. 4. Change code then run the examples. -5. Push your branch to Github after all tests passed. +5. [Push your branch to Github after all tests passed.](#Testing) 6. Make a [pull request](https://github.com/alephjs/aleph.js/pulls). 7. Merge to master branch by our maintainers. @@ -29,9 +29,21 @@ ALEPH_DEV=true deno run -A --unstable --location=http://localhost cli.ts start . # ssg ALEPH_DEV=true deno run -A --unstable --location=http://localhost cli.ts build ./examples/hello-world -L debug +``` + +## Testing + +You can run all tests with the following command: + +```bash +$ deno test -A --unstable --location=http://localhost -c=deno.json --import-map=import_map.json +``` + +After running `integration_test.ts`, a zombie subprocesse may remain alive. (See [denoland/deno#7087](https://github.com/denoland/deno/issues/7087) for details) You can get rid of it with the following command: -# run all tests -deno test -A --unstable --location=http://localhost -c=deno.json --import-map=import_map.json +```shell +# On Unix +$ kill $(lsof -i:8080 -t) ``` ## Project Structure diff --git a/integration_test.ts b/integration_test.ts new file mode 100644 index 000000000..3e166c18a --- /dev/null +++ b/integration_test.ts @@ -0,0 +1,87 @@ +import { + assert, + assertEquals, + assertStringIncludes +} from 'std/testing/asserts.ts' +import { emptyDir } from 'std/fs/mod.ts' +import { BufReader } from 'std/io/bufio.ts' +import { DOMParser } from 'https://deno.land/x/deno_dom@v0.1.15-alpha/deno-dom-wasm.ts' + +Deno.test('integration: dev command', async () => { + const distDir = './examples/hello-world/dist' + await emptyDir(distDir) + localStorage.removeItem('count') + + const buildCmd = aleph(['dev', './examples/hello-world', '--port', '8080']) + try { + const port = await waitForServerToStart(buildCmd) + + // Call /api/counter/increase twice + let res = await fetch(`http://localhost:${port}/api/counter/increase`) + assert(res.ok) + assertEquals(await res.json(), { count: 1 }) + + res = await fetch(`http://localhost:${port}/api/counter/increase`) + assert(res.ok) + assertEquals(await res.json(), { count: 2 }) + + // Get index page + const parser = new DOMParser() + res = await fetch(`http://localhost:${port}`) + const html = await res.text() + const doc = parser.parseFromString(html, 'text/html') + assert(doc) + + const copyinfo = doc.querySelector('.copyinfo') + assert(copyinfo) + assertStringIncludes(copyinfo.textContent, 'Built by Aleph.js in Deno') + } finally { + cleanupAlephProcess(buildCmd) + } +}) + +function aleph(cmd: Array): Deno.Process { + return Deno.run({ + cmd: [ + Deno.execPath(), + 'run', + '-A', + '--unstable', + '--location=http://localhost', + 'cli.ts', + ...cmd + ], + env: { + 'ALEPH_DEV': 'true', + 'NO_COLOR': 'true' + }, + stdout: "piped", + }) +} + +function cleanupAlephProcess(process: Deno.Process): void { + if (process.stdout) { + process.stdout.close() + } + process.close() +} + +// Waits for the aleph server to start and returns a port +async function waitForServerToStart(process: Deno.Process): Promise { + assert(process.stdout) + const buf = BufReader.create(process.stdout) + const decoder = new TextDecoder() + while (true) { + const result = await buf.readLine() + if (result == null) { + throw new Error('Unexpected EOF') + } + + const { line } = result + const match = /^INFO Server ready on http:\/\/localhost:(\d+).*$/.exec(decoder.decode(line)) + if (match) { + const [, port] = match + return parseInt(port) + } + } +}