There are no Grammarly applications that could deliver integration with at least command-line. So let's make selenium automation that will paste text into Grammarly documents!
S0-E16/E30 :)
Grammarly Integration
For now [mid-February 2018] Grammarly does not give their users API that you could use in integrations with some blogging engines, but instead, you can use their Android/iOS spelling keyboard on your mobile or use Web-browser.
There are integrations for Chrome as a plugin, Firefox addon and native in Windows and MacOS.
Since I'm a more into Linux - There is no real alternative than using their web-app.
Yes, they are excellent and I still use them. But for now, I don't have mobile-integration for my blogging experience, as Pelican is a static-site generator and I store files on my computer. I'm planning to make some automations, and this post is one of them :)
The best thing for now that I still do is manually copy-paste the actual text of blog-post and put it in Google-Keep and then use Grammarly Firefox Plugin. That seems a bit silly and not as handy as an Automation that could do that for me.
Selenium automation for Grammarly
So I said to myself - why not create Selenium automation that will at least put actual text of blog-post into Grammarly Document?
Grammarly-Selenium-Automation project init.
First, let's create a repository on GitHub called grammarly-selenium-automation
.
Then Let's make git-repo with:
mkdir grammarly-selenium-automation
cd grammarly-selenium-automation
git init .
git commit --allow-empty -m "Init"
wget https://www.gitignore.io/api/vim%2Cpython -O .gitignore
git add .gitignore
git commit -m "Adds gitignore"
git remote add origin git@github.com:anselmos/grammarly-selenium-automation.git
git push -u origin master
And now we have our repository available on github.
Now let's make actual selenium login-automation.
Grammarly Selenium login script.
For this script, I'll use one of my previous blog posts about making selenium-automation.
BTW - I've ofcourse forgot about making a virtualenv for using selenium :
cd grammarly-selenium-automation && virtualenv .env && source .env/bin/activate && pip install selenium && pip freeze > requirements.txt
git add requirements.txt
git commit -m "Adds pip requirements.txt"
git push origin HEAD:master
And now the script:
login.py
script
import unittest
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from grammarly_page import GrammarlyLogin
import time
class GrammarlyGeneralTest(unittest.TestCase):
def setUp(self):
# for dev I'll use only visible browser instead of no-gui one.
# but for production, it will use the no-gui one.
# self.driver = webdriver.Firefox()
# TODO uncomment it when finished coding.
self.driver = webdriver.Remote(
command_executor='http://127.0.0.1:4444/wd/hub',
desired_capabilities={'browserName': 'firefox', 'javascriptEnabled': True}
)
def test_grammarly_in_title(self):
page_login = GrammarlyLogin(self.driver)
self.driver.get(page_login.uri)
assert "Grammarly" in self.driver.title
def test_login(self):
page_login = GrammarlyLogin(self.driver)
page_login.make_login('za2217279@mvrht.net', 'test123')
time.sleep(2)
assert self.driver.current_url == "https://app.grammarly.com/"
def tearDown(self):
self.driver.close()
if __name__ == "__main__":
unittest.main()
and the grammarly_page.py
:
from page_objects import PageObject, PageElement
class GrammarlyLogin(PageObject):
username = PageElement(css='input[type="email"]')
password = PageElement(css='input[type="password"]')
login = PageElement(css='button[type="submit"]')
uri = 'https://www.grammarly.com'
signin_uri = '/signin'
def make_login(self, username, password):
self.get(self.uri + self.signin_uri)
self.username = username
self.password = password
self.login.click()
You can find it also at this repo tag: login-page-done
Grammarly Selenium adds new file:
Now ! :) to the fun-part :) Let's make a new document in Grammarly and push it to the grammarly with copying data.
While I was working on making new doc script, I've decided to change naming of the login.py
file into tests.py
- because I thought it will be more meaningful - since that's what it contains :)
Moving on :
Within grammarly_page.py
I've added this:
class GrammarlyNewDocument(PageObject):
uri = 'https://app.grammarly.com/'
new_document = PageElement(css='div[role="button"]')
def make_new_document(self, name=None):
self.get(self.uri)
self.new_document.click()
time.sleep(2)
class GrammarlyDocument(PageObject):
title = PageElement(css='input[type="text"]')
text = PageElement(id_='textarea')
def put_title(self, title):
self.title = title
def put_text(self, text):
self.text = text
And on the tests.py
I've added this:
def test_make_new_doc(self):
page_login = GrammarlyLogin(self.driver)
page_login.make_login('za2217279@mvrht.net', 'test123')
page_new_doc = GrammarlyNewDocument(self.driver)
page_new_doc.make_new_document("TEST")
assert "https://app.grammarly.com/docs/" in self.driver.current_url
def test_change_title_on_doc(self):
page_login = GrammarlyLogin(self.driver)
page_login.make_login('za2217279@mvrht.net', 'test123')
page_new_doc = GrammarlyNewDocument(self.driver)
page_new_doc.make_new_document("")
page_doc = GrammarlyDocument(self.driver)
self.assert_title(page_doc)
def test_change_text_on_doc(self):
page_login = GrammarlyLogin(self.driver)
page_login.make_login('za2217279@mvrht.net', 'test123')
page_new_doc = GrammarlyNewDocument(self.driver)
page_new_doc.make_new_document("")
page_doc = GrammarlyDocument(self.driver)
self.assert_text(page_doc)
def test_change_title_and_text_on_doc(self):
page_login = GrammarlyLogin(self.driver)
page_login.make_login('za2217279@mvrht.net', 'test123')
page_new_doc = GrammarlyNewDocument(self.driver)
page_new_doc.make_new_document("")
page_doc = GrammarlyDocument(self.driver)
self.assert_title(page_doc)
self.assert_text(page_doc)
def assert_title(self, page_doc):
title_expected = "NewTestTitle"
page_doc.put_title(title_expected)
time.sleep(2)
actual_doc = GrammarlyDocument(self.driver)
self.assertEquals(page_doc.title, actual_doc.title)
def assert_text(self, page_doc):
text_expected = "A very bad text that are have some issues and Grammarly Should find problems with it"
page_doc.put_text(text_expected)
time.sleep(2)
actual_doc = GrammarlyDocument(self.driver)
self.assertEquals(page_doc.text, actual_doc.text)
You can check the whole project in this state at tag: doc-title-and-text
Pelican plugin for Grammarly
That's just a POC for making Grammarly and Selenium Automation. In part2 I'll try to make integration with the pelican engine.
This time I'll focus my attention on gathering as much as I can from the Grammarly document Checker. :)
Acknowledgements
- C0nn3r-Reverse-engineering-grammarly-api
- Grammarly On Twitter - No API yet
- Building Browser Extensions at scale
- grammar - is 'Grammarly' really that good?
- Selenium Page Object Pattern for python
- Page-Objects python lib
Grammarly Alternatives: - TextGears - this one has an API that you could use. ( and payment for amount of requests/data sent)
Thanks!
That's it :) Comment, share or don't :)
If you have any suggestions what I should blog about in the next articles - please give me a hint :)
See you tomorrow! Cheers!
Comments
comments powered by Disqus