- Very good README included
- Meets the functional requirements from the specification
- Good test coverage, acceptance and integration
- Nice to see TypeScript used
- Responsive design implemented
- Access token entered via .env file, and .env.example file provided
-
Styling some elements by HTML tag name rather than classes
[+] only global reset styles are applied to elements, all others apply to class names
-
Performing some testing assertions using HTML tag names rather than always sticking with ember-test-selectors
[+] all queries done with
data-test-*selectors -
Setting
innerHTMLon parts of the template from the component and using methods likeclassList.toggle, rather than relying on tracked properties to control different template states[+] reworked approach with
BranchesRowcomponent and custom modifier triggering branches API call on a first render. As a sideeffect: only single row of branches at a time can be visible, if user clicks on another repository row, the row with branches for a previous one collapses -
Using
data-test-*selector for selecting elements in the component, rather than only using those selectors for test environments (data-test-*selectors are removed from production builds by default which can potentially cause issues)[+] my bad: reworked solution with Ember approach by introducing
BranchesRowcomponent -
If an invalid access token is used and the app fails to load any repos, it does not seem to communicate the problem to the user (saw that ember-cli-notifications was installed, but it doesn't seem to show that error for us)
[+] added 401 error check
I had two approaches at my disposal:
-
Build an app quickly with familiar but older conventions (the setup I used to work on my previous project):
- glimmer
- co-located components with
.jsand.hbsfiles - Broccoli.js build tool
npm, or:
-
Invest more time in building the app and learning the latest recommended practices, including:
- first-class component templates
- Embroider build system
- TypeScript
pnpm
Based on my experience, investing efforts into learning and implementing the latest practices always pays off by:
- pushing off a technical debt piling up soon enough
- the codebase is more stable, free from deprecations, and with security support from Ember LTS versions
-
I experimented with the following Ember app setup
- Polaris edition:
ember-source@v~6.2.0 - Embroider build system
- written with TypeScript
- components are defined in
.gtsand use<template> - no
ember-data
- Polaris edition:
-
Third-party addons used and
not usedI followed the approach of using as few dependencies as necessary to complete the task.
ember-cli-dotenv- for shielding sensitive dataember-concurrency- for handling REST API calls, loading state, and error managementember-test-selectors- for testing convenience on querying elementsember-cli-notifications- for notifying errored API callsember-truth-helpers-eqhelper used incomponents/repos/filter.gtstemplate
I also considered other addons, but I got away with browsers widely supported The HTML DOM API
-
Forms and Validation:
ember-headless-form < HTML forms with native form validation
-
Styling:
Tailwind CSS / ember-bootstrap < CSS
-
Handling data:
ember-data
-
ember-cli-dotenvTo keep sensitive data from publishing to a remote repository, I introduced
.envfor environment variables:- GitHub PAT (Classic) is stored in
GITHUB_PAT_CLASSIC .envshould be handled locally only.env.example- is available in the remote repository with all used environment variables (in our case - just one)GITHUB_PAT_CLASSICis set indevelopmentandtestenvironments only
- GitHub PAT (Classic) is stored in
-
No
ember-data- the app is not modifying any received data - it just displays the data it gets
- I understand that for demonstrating my expertise, it would be better to use
ember-data, although due to the deprecation of adapters & serializers paradigm and encouragement to switch toHandlerswithRequestManager, I chose to ditchember-datacompletely, rather than invest more time into masteringRequestManager
-
A single
applicationroute is used for simplicity:- the drawback: the state is NOT persistent on page reload
- for a state-preserving solution, I would use a route
repo/:repo_namewithember-datamodelsrepository&branchwith a relationship: repositoryhasManybranches - for filtering, I would use route
queryParams, as well as would add a pagination support
-
Repositories filtering
- filters are implemented via radio groups
- filters handle
nullvalue onlanguagetype Allis a default value for bothlanguageandprivacyfilters. Thus all repositories are listed initially
-
Styling
- I decided to use minimal design, no fancy looks, no external libraries, just plain functionality, and minimum CSS
- each repository row is clickable and behaves like a drawer for the row below with a branches list
- implemented responsive design: supports desktop and mobile views
- icons are taken from AmpWhat
-
App functionality decisions
-
No excess, duplicate, or unnecessary API calls:
- disabling
find org reposbutton while API call in-flight - in
BranchesRowcomponent branches API call is called once on initial render - setting
getRepoBranchestask droppable
- disabling
-
Reset logic:
- filters are reset on a new org API call
-
-
REST API calls
The task requires showing a column with the total number of branches. The
org/reposAPI is not returning any data related to branches. There is a separaterepo/branchesendpoint. I am not calling it after the repositories list is rendered, as doing 30 calls at once doesn't make much sense in our case:- branches list is hidden from a view initially
- the data is displayed on user interaction, so data is fetched only when and which needed
-
Testing
ember-concurrencyand tests do not play very nice. In particular, I failed to write a test scenario for checking the loading state while API calls are in flight
You will need the following things properly installed on your computer.
- Git
- Node.js
- pnpm
- Ember CLI
- Last 1 version of either browser: Google Chrome // Mozilla Firefox // Safari
git clone <repository-url>this repositorycd dealfrontpnpm i
Before starting the app, assign your GitHub account PAT (classic) into the GITHUB_PAT_CLASSIC environment variable in .env.
When creating a .env file, make a copy from .env.exmaple.
pnpm start- Visit your app at http://localhost:4200.
- Visit your tests at http://localhost:4200/tests.
pnpm testpnpm test:ember --server