From 8ab6a0a2805e072b08655f1f7023dfdeaa063ef9 Mon Sep 17 00:00:00 2001 From: Florian Loitsch Date: Sun, 15 Feb 2026 22:43:51 +0100 Subject: [PATCH 1/2] Add tests. --- .github/workflows/ci.yml | 11 +++ .gitignore | 2 + README.md | 10 +-- cypress.json | 4 +- cypress/integration/docs.spec.ts | 114 +++++++++++++++++++++++++++++++ tests/generate_test_data.sh | 29 ++++++++ 6 files changed, 164 insertions(+), 6 deletions(-) create mode 100644 cypress/integration/docs.spec.ts create mode 100755 tests/generate_test_data.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 021b61a7b..7343c11e2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -73,6 +73,17 @@ jobs: run: | yarn lint + - name: Setup Toit + if: ${{ github.event.inputs.run-tests != 'false' }} + uses: toitlang/action-setup@v1 + with: + toit-version: v2.0.0-alpha.189 + + - name: Generate test data + if: ${{ github.event.inputs.run-tests != 'false' }} + run: | + tests/generate_test_data.sh + - name: Test if: ${{ github.event.inputs.run-tests != 'false' }} run: | diff --git a/.gitignore b/.gitignore index dd63e6e7f..e471c392d 100644 --- a/.gitignore +++ b/.gitignore @@ -145,3 +145,5 @@ sketch # End of https://www.toptal.com/developers/gitignore/api/yarn,node,react .packages/ +public/toitdoc*.json +cypress_output*.txt diff --git a/README.md b/README.md index 41347f426..3c7f03edb 100644 --- a/README.md +++ b/README.md @@ -67,20 +67,20 @@ You can create new json files by running the following command: ### Core libraries ```bash -toit doc build --sdk --out "$OUTFILE" +toit doc build --sdk --output "$OUTFILE" ``` ### Package ```bash -toit doc build --package --out "$OUTFILE" $PATH_TO_PACKAGE +toit doc build --package --output "$OUTFILE" $PATH_TO_PACKAGE ``` You might want to exclude the sdk and/or packages from the generated documentation: ```bash -toit doc build --package --exclude-sdk --out "$OUTFILE" $PATH_TO_PACKAGE -toit doc build --package --exclude-pkgs --out "$OUTFILE" $PATH_TO_PACKAGE +toit doc build --package --exclude-sdk --output "$OUTFILE" $PATH_TO_PACKAGE +toit doc build --package --exclude-pkgs --output "$OUTFILE" $PATH_TO_PACKAGE ``` ### Folder @@ -88,7 +88,7 @@ toit doc build --package --exclude-pkgs --out "$OUTFILE" $PATH_TO_PACKAGE You can also just build the toitdoc of a folder: ```bash -toit doc build --out "$OUTFILE" $PATH_TO_FOLDER +toit doc build --output "$OUTFILE" $PATH_TO_FOLDER ``` ## Cloudflare diff --git a/cypress.json b/cypress.json index 0967ef424..17ef242e7 100644 --- a/cypress.json +++ b/cypress.json @@ -1 +1,3 @@ -{} +{ + "baseUrl": "http://localhost:3000" +} diff --git a/cypress/integration/docs.spec.ts b/cypress/integration/docs.spec.ts new file mode 100644 index 000000000..c005f268f --- /dev/null +++ b/cypress/integration/docs.spec.ts @@ -0,0 +1,114 @@ +/// + +describe('Documentation Viewer', () => { + beforeEach(() => { + // Increase default timeout for all tests as loading/rendering might be slow, especially for SDK + Cypress.config('defaultCommandTimeout', 30000); + }); + + const checkSidebarGroup = (label: string) => { + // The sidebar might use different structures. This is a generic check. + cy.contains(label).should('be.visible'); + }; + + describe('Package Mode', () => { + beforeEach(() => { + // Load the package-specific json + cy.readFile('public/toitdoc_pkg.json').then((json) => { + json.mode = 'package'; + cy.intercept('GET', '/toitdoc.json', json).as('getDocs'); + }); + cy.visit('/'); + cy.wait('@getDocs'); + }); + + it('loads the package view', () => { + cy.get('body').should('contain.text', 'pkg'); + // Enhanced assertions + // Sidebar "Libraries" header + cy.contains('h5', 'Libraries').should('be.visible'); + // Sidebar "pkg" item + cy.contains('pkg').should('be.visible'); + cy.contains('h3', 'Functions').should('be.visible'); + // Check function signatures + cy.contains('foo str/string').should('be.visible'); + cy.contains(' -> string').should('be.visible'); + cy.contains('bar a/A').should('be.visible'); + cy.contains(' -> A').should('be.visible'); + }); + + it('navigates to class A', () => { + cy.contains('pkg').click(); + cy.contains('foo').should('be.visible'); + cy.contains('bar').should('be.visible'); + + // Click on 'A' explicitly within the Classes section. + cy.contains('h3', 'Classes').parent().parent().within(() => { + cy.contains('a', /^A$/).click(); + }); + cy.contains('Class A').should('be.visible'); + + // Enhanced assertions for Class A + cy.contains('extends Object').should('be.visible'); + cy.contains('h3', 'Methods').should('be.visible'); + cy.contains('operator == other/any').should('be.visible'); + cy.contains(' -> bool').should('be.visible'); + cy.contains('stringify').should('be.visible'); + cy.contains(' -> string').should('be.visible'); + }); + }); + + describe('Folder/SDK Mode', () => { + beforeEach(() => { + // Load the folder/sdk-like json + cy.readFile('public/toitdoc_folder.json').then((json) => { + delete json.mode; // mode undefined means Folder view in doc.ts + cy.intercept('GET', '/toitdoc.json', json).as('getDocs'); + }); + Cypress.config('defaultCommandTimeout', 30000); + cy.visit('/'); + cy.wait('@getDocs'); + cy.get('.MuiCircularProgress-root').should('not.exist'); + }); + + it('loads the folder view', () => { + cy.get('body').should('contain.text', 'pkg'); + // Enhanced assertions + cy.contains('Toitdoc Viewer').should('be.visible'); + cy.contains('Welcome to the Toitdoc viewer').should('be.visible'); + cy.contains('Libraries').should('be.visible'); + cy.contains('other').should('be.visible'); + cy.contains('pkg').should('be.visible'); + }); + }); + + describe('SDK Mode', () => { + beforeEach(() => { + // Load the sdk json + cy.readFile('public/toitdoc_sdk.json').then((json) => { + json.mode = 'sdk'; + cy.intercept('GET', '/toitdoc.json', json).as('getDocs'); + }); + cy.visit('/'); + cy.wait('@getDocs'); + }); + + it('loads the sdk view and shows Core library', () => { + cy.get('body').should('contain.text', 'core'); + // Navigate to 'core' + cy.contains('core').click(); + + // Enhanced assertions for SDK Core + cy.contains('Library core').should('be.visible'); + cy.contains('h3', 'Exported classes').should('be.visible'); + cy.contains('h3', 'Exported functions').should('be.visible'); + + // Check for common core classes/functions + cy.contains('bool').should('be.visible'); + cy.contains('int').should('be.visible'); + cy.contains('string').should('be.visible'); + cy.contains('List').should('be.visible'); + cy.contains('print message/any').should('be.visible'); + }); + }); +}); diff --git a/tests/generate_test_data.sh b/tests/generate_test_data.sh new file mode 100755 index 000000000..812695e85 --- /dev/null +++ b/tests/generate_test_data.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# Exit on error +set -e + +# Go to the project root +cd "$(dirname "$0")/.." + +# Install dependencies for the test package +echo "Installing dependencies for test-pkg..." +toit pkg install --project-root=tests/test-pkg + +# Generate the toitdoc.json for the package (default for now) +echo "Generating public/toitdoc.json from test-pkg..." +toit doc build --package --output public/toitdoc.json tests/test-pkg + +# Generate a separate package json for specific tests +echo "Generating public/toitdoc_pkg.json..." +toit doc build --package --output public/toitdoc_pkg.json tests/test-pkg + +# Generate SDK documentation +echo "Generating public/toitdoc_sdk.json..." +toit doc build --sdk --output public/toitdoc_sdk.json + +# Generate basic folder documentation +echo "Generating public/toitdoc_folder.json..." +toit doc build --output public/toitdoc_folder.json tests/test-pkg/src + +echo "Done." From 8ce68aaaa8839a6f6874e0ea40ca489ba7e74f2d Mon Sep 17 00:00:00 2001 From: Florian Loitsch Date: Sun, 15 Feb 2026 22:46:47 +0100 Subject: [PATCH 2/2] Fix linting errors. --- cypress/integration/docs.spec.ts | 131 ++++++++++++++++--------------- 1 file changed, 67 insertions(+), 64 deletions(-) diff --git a/cypress/integration/docs.spec.ts b/cypress/integration/docs.spec.ts index c005f268f..959a25213 100644 --- a/cypress/integration/docs.spec.ts +++ b/cypress/integration/docs.spec.ts @@ -1,114 +1,117 @@ /// -describe('Documentation Viewer', () => { +describe("Documentation Viewer", () => { beforeEach(() => { // Increase default timeout for all tests as loading/rendering might be slow, especially for SDK - Cypress.config('defaultCommandTimeout', 30000); + Cypress.config("defaultCommandTimeout", 30000); }); const checkSidebarGroup = (label: string) => { // The sidebar might use different structures. This is a generic check. - cy.contains(label).should('be.visible'); + cy.contains(label).should("be.visible"); }; - describe('Package Mode', () => { + describe("Package Mode", () => { beforeEach(() => { // Load the package-specific json - cy.readFile('public/toitdoc_pkg.json').then((json) => { - json.mode = 'package'; - cy.intercept('GET', '/toitdoc.json', json).as('getDocs'); + cy.readFile("public/toitdoc_pkg.json").then((json) => { + json.mode = "package"; + cy.intercept("GET", "/toitdoc.json", json).as("getDocs"); }); - cy.visit('/'); - cy.wait('@getDocs'); + cy.visit("/"); + cy.wait("@getDocs"); }); - it('loads the package view', () => { - cy.get('body').should('contain.text', 'pkg'); + it("loads the package view", () => { + cy.get("body").should("contain.text", "pkg"); // Enhanced assertions // Sidebar "Libraries" header - cy.contains('h5', 'Libraries').should('be.visible'); + cy.contains("h5", "Libraries").should("be.visible"); // Sidebar "pkg" item - cy.contains('pkg').should('be.visible'); - cy.contains('h3', 'Functions').should('be.visible'); + cy.contains("pkg").should("be.visible"); + cy.contains("h3", "Functions").should("be.visible"); // Check function signatures - cy.contains('foo str/string').should('be.visible'); - cy.contains(' -> string').should('be.visible'); - cy.contains('bar a/A').should('be.visible'); - cy.contains(' -> A').should('be.visible'); + cy.contains("foo str/string").should("be.visible"); + cy.contains(" -> string").should("be.visible"); + cy.contains("bar a/A").should("be.visible"); + cy.contains(" -> A").should("be.visible"); }); - it('navigates to class A', () => { - cy.contains('pkg').click(); - cy.contains('foo').should('be.visible'); - cy.contains('bar').should('be.visible'); + it("navigates to class A", () => { + cy.contains("pkg").click(); + cy.contains("foo").should("be.visible"); + cy.contains("bar").should("be.visible"); // Click on 'A' explicitly within the Classes section. - cy.contains('h3', 'Classes').parent().parent().within(() => { - cy.contains('a', /^A$/).click(); - }); - cy.contains('Class A').should('be.visible'); + cy.contains("h3", "Classes") + .parent() + .parent() + .within(() => { + cy.contains("a", /^A$/).click(); + }); + cy.contains("Class A").should("be.visible"); // Enhanced assertions for Class A - cy.contains('extends Object').should('be.visible'); - cy.contains('h3', 'Methods').should('be.visible'); - cy.contains('operator == other/any').should('be.visible'); - cy.contains(' -> bool').should('be.visible'); - cy.contains('stringify').should('be.visible'); - cy.contains(' -> string').should('be.visible'); + cy.contains("extends Object").should("be.visible"); + cy.contains("h3", "Methods").should("be.visible"); + cy.contains("operator == other/any").should("be.visible"); + cy.contains(" -> bool").should("be.visible"); + cy.contains("stringify").should("be.visible"); + cy.contains(" -> string").should("be.visible"); }); }); - describe('Folder/SDK Mode', () => { + describe("Folder/SDK Mode", () => { beforeEach(() => { - // Load the folder/sdk-like json - cy.readFile('public/toitdoc_folder.json').then((json) => { + // Load the folder/sdk-like json + cy.readFile("public/toitdoc_folder.json").then((json) => { delete json.mode; // mode undefined means Folder view in doc.ts - cy.intercept('GET', '/toitdoc.json', json).as('getDocs'); + cy.intercept("GET", "/toitdoc.json", json).as("getDocs"); }); - Cypress.config('defaultCommandTimeout', 30000); - cy.visit('/'); - cy.wait('@getDocs'); - cy.get('.MuiCircularProgress-root').should('not.exist'); + Cypress.config("defaultCommandTimeout", 30000); + cy.visit("/"); + cy.wait("@getDocs"); + cy.get(".MuiCircularProgress-root").should("not.exist"); }); - it('loads the folder view', () => { - cy.get('body').should('contain.text', 'pkg'); + it("loads the folder view", () => { + cy.get("body").should("contain.text", "pkg"); // Enhanced assertions - cy.contains('Toitdoc Viewer').should('be.visible'); - cy.contains('Welcome to the Toitdoc viewer').should('be.visible'); - cy.contains('Libraries').should('be.visible'); - cy.contains('other').should('be.visible'); - cy.contains('pkg').should('be.visible'); + cy.contains("Toitdoc Viewer").should("be.visible"); + cy.contains("Welcome to the Toitdoc viewer").should("be.visible"); + cy.contains("Libraries").should("be.visible"); + cy.contains("other").should("be.visible"); + cy.contains("pkg").should("be.visible"); }); }); - describe('SDK Mode', () => { + describe("SDK Mode", () => { beforeEach(() => { // Load the sdk json - cy.readFile('public/toitdoc_sdk.json').then((json) => { - json.mode = 'sdk'; - cy.intercept('GET', '/toitdoc.json', json).as('getDocs'); + cy.readFile("public/toitdoc_sdk.json").then((json) => { + json.mode = "sdk"; + cy.intercept("GET", "/toitdoc.json", json).as("getDocs"); }); - cy.visit('/'); - cy.wait('@getDocs'); + cy.visit("/"); + cy.wait("@getDocs"); }); - it('loads the sdk view and shows Core library', () => { - cy.get('body').should('contain.text', 'core'); + it("loads the sdk view and shows Core library", () => { + cy.get("body").should("contain.text", "core"); // Navigate to 'core' - cy.contains('core').click(); + cy.contains("core").click(); // Enhanced assertions for SDK Core - cy.contains('Library core').should('be.visible'); - cy.contains('h3', 'Exported classes').should('be.visible'); - cy.contains('h3', 'Exported functions').should('be.visible'); + cy.contains("Library core").should("be.visible"); + cy.contains("h3", "Exported classes").should("be.visible"); + cy.contains("h3", "Exported functions").should("be.visible"); // Check for common core classes/functions - cy.contains('bool').should('be.visible'); - cy.contains('int').should('be.visible'); - cy.contains('string').should('be.visible'); - cy.contains('List').should('be.visible'); - cy.contains('print message/any').should('be.visible'); + cy.contains("bool").should("be.visible"); + cy.contains("int").should("be.visible"); + cy.contains("string").should("be.visible"); + cy.contains("List").should("be.visible"); + cy.contains("print message/any").should("be.visible"); }); }); });