diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0a324a4..d82d927 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,19 +1,6 @@ # Contributing to Pinafore -## Caveats - -Please note that this project is _very_ beta right now, and I'm -not in a good position to accept large PRs for -big new features. - -I'm making my code open-source for the sake of -transparency and because it's the right thing to do, but I'm hesitant -to start nurturing a community because of -[all that entails](https://nolanlawson.com/2017/03/05/what-it-feels-like-to-be-an-open-source-maintainer/). - -So I may not be very responsive to PRs or issues. Thanks for understanding. - -## Development +## Dev server To run a dev server with hot reloading: @@ -37,9 +24,17 @@ Automatically fix most linting issues: npm run lint-fix -## Testing +## Integration tests -Testing requires running Mastodon itself, meaning the [Mastodon development guide](https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/Development-guide.md) is relevant here. In particular, you'll need a recent version of Ruby, Redis, and Postgres running. +Integration tests use [TestCafé](https://devexpress.github.io/testcafe/) and a live local Mastodon instance +running on `localhost:3000`. + +### Running integration tests + +The integration tests require running Mastodon itself, +meaning the[Mastodon development guide](https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/Development-guide.md) +is relevant here. In particular, you'll need a recent +version of Ruby, Redis, and Postgres running. For a full list of deps, see `bin/setup-mastodon-in-travis.sh`. Run integration tests, using headless Chrome by default: @@ -54,7 +49,7 @@ Run tests for a particular browser: BROWSER=safari npm run test-browser BROWSER=edge npm run test-browser -## Testing in development mode +### Testing in development mode In separate terminals: @@ -68,33 +63,46 @@ In separate terminals: 3\. Run a debuggable TestCafé instance: - npx testcafe --hostname localhost --skip-js-errors --debug-mode firefox tests/spec + npx testcafe --hostname localhost --skip-js-errors --debug-mode chrome tests/spec -If you want to export the current data in the Mastodon instance as canned data, -so that it can be loaded later, run: +### Test conventions - npm run backup-mastodon-data +The tests have a naming convention: -## Writing tests - -Tests use [TestCafé](https://devexpress.github.io/testcafe/). The tests have a naming convention: - -* `0xx-test-name.js`: tests that don't modify the Mastodon database (post, delete, follow, etc.) -* `1xx-test-name.js`: tests that do modify the Mastodon database +* `0xx-test-name.js`: tests that don't modify the Mastodon database (read-only) +* `1xx-test-name.js`: tests that do modify the Mastodon database (read-write) In principle the `0-` tests don't have to worry about clobbering each other, whereas the `1-` ones do. -## Debugging Webpack +### Mastodon used for testing -The Webpack Bundle Analyzer `report.html` and `stats.json` are available publicly via e.g.: +There are two parts to the Mastodon data used for testing: -- [dev.pinafore.social/report.html](https://dev.pinafore.social/report.html) -- [dev.pinafore.social/stats.json](https://dev.pinafore.social/stats.json) +1. A Postgres dump and a tgz containing the media files, located in `fixtures` +2. A script that populates the Mastodon backend with test data (`restore-mastodon-data.js`). -This is also available locally after `npm run build` at `.sapper/client/report.html`. +The reason we don't use a Postgres dump for everything +is that Mastodon will ignore changes made after a certain period of time, and we +don't want our tests to randomly start breaking one day. Running the script ensures that statuses, +favorites, boosts, etc. are all "fresh". -## Updating Mastodon used for testing +### Updating the test data + +You probably don't want to do this, as the `0xx` tests are pretty rigidly defined against the test data. +Write a `1xx` test instead and insert what you need on-the-fly. + +If you really need to, though, you can either: + +1. Add new test data to `mastodon-data.js` + +or + +1. Comment out `await restoreMastodonData()` in `run-mastodon.js` +2. Make your changes manually to the live Mastodon +3. Run the steps in the next section to back it up to `fixtures/` + +### Updating the Mastodon version 1. Run `rm -fr mastodon` to clear out all Mastodon data 1. Comment out `await restoreMastodonData()` in `run-mastodon.js` to avoid actually populating the database with statuses/favorites/etc. @@ -111,3 +119,62 @@ Check `mastodon.log` if you have any issues. There are also some unit tests that run in Node using Mocha. You can find them in `tests/unit` and run them using `npm run test-unit`. + +## Debugging Webpack + +The Webpack Bundle Analyzer `report.html` and `stats.json` are available publicly via e.g.: + +- [dev.pinafore.social/report.html](https://dev.pinafore.social/report.html) +- [dev.pinafore.social/stats.json](https://dev.pinafore.social/stats.json) + +This is also available locally after `npm run build` at `.sapper/client/report.html`. + +## Codebase overview + +Pinafore uses [SvelteJS](https://svelte.technology) and [SapperJS](https://sapper.svelte.technology). Most of it is a fairly typical Svelte/Sapper project, but there +are some quirks, which are described below. This list of quirks is non-exhaustive. + +### Prebuild process + +The `template.html` is itself templated. The "template template" has some inline scripts, CSS, and SVGs +injected into it during the build process. SCSS is used for global CSS and themed CSS, but inside of the +components themselves, it's just vanilla CSS because I couldn't figure out how to get Svelte to run a SCSS +preprocessor. + +### Lots of small files + +Highly modular, highly functional, lots of single-function files. Tends to help with tree-shaking and +code-splitting, as well as avoiding circular dependencies. + +### Inferno is loaded dynamically + +This is a Svelte project, but `emoji-mart` is used for the emoji picker, and it's written in React. So we +lazy-load the React-compatible Inferno library when we load `emoji-mart`. + +### Some third-party code is bundled + +For various reasons, `a11y-dialog`, `autosize`, and `timeago` are forked and bundled into the source code. +This was either because something needed to be tweaked or fixed, or I was trimming unused code and didn't +see much value in contributing it back, because it was too Pinafore-specific. + +### Every Sapper page is "duplicated" + +To get a nice animation on the nav bar when you switch columns, every page is lazy-loaded as `LazyPage.html`. +This "lazy page" is merely delayed a few frames to let the animation run. Therefore there is a duplication +between `src/routes` and `src/routes_pages`. The "lazy page" is in the former, and the actual page is in the +latter. One imports the other. + +### There are multiple stores + +Originally I conceived of separating out the virtual list into a separate npm package, so I gave it its +own Svelte store (`virtualListStore.js`). This never happened, but it still has its own store. This is useful +anyway, because each store has its state maintained in an LRU cache that allows us to keep the scroll position +in the virtual list e.g. when the user hits the back button. + +Also, the main `store.js` store is explicitly +loaded by every component that uses it. So there's no `store` inheritance; every component just declares +whatever store it uses. The main `store.js` is the primary one. + +### There is a global event bus + +It's in `eventBus.js`. This is useful for some stuff that is hard to do with standard Svelte or DOM events.