codeceptjs 3.5.12-beta.2 → 3.5.12-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (213) hide show
  1. package/lib/locator.js +7 -12
  2. package/package.json +3 -5
  3. package/docs/advanced.md +0 -351
  4. package/docs/ai.md +0 -248
  5. package/docs/api.md +0 -323
  6. package/docs/basics.md +0 -979
  7. package/docs/bdd.md +0 -539
  8. package/docs/best.md +0 -237
  9. package/docs/books.md +0 -37
  10. package/docs/bootstrap.md +0 -135
  11. package/docs/build/ApiDataFactory.js +0 -410
  12. package/docs/build/Appium.js +0 -2027
  13. package/docs/build/Expect.js +0 -422
  14. package/docs/build/FileSystem.js +0 -228
  15. package/docs/build/GraphQL.js +0 -229
  16. package/docs/build/GraphQLDataFactory.js +0 -309
  17. package/docs/build/JSONResponse.js +0 -338
  18. package/docs/build/Mochawesome.js +0 -71
  19. package/docs/build/Nightmare.js +0 -2152
  20. package/docs/build/OpenAI.js +0 -126
  21. package/docs/build/Playwright.js +0 -5110
  22. package/docs/build/Protractor.js +0 -2706
  23. package/docs/build/Puppeteer.js +0 -3905
  24. package/docs/build/REST.js +0 -344
  25. package/docs/build/TestCafe.js +0 -2125
  26. package/docs/build/WebDriver.js +0 -4240
  27. package/docs/changelog.md +0 -2572
  28. package/docs/commands.md +0 -266
  29. package/docs/community-helpers.md +0 -58
  30. package/docs/configuration.md +0 -157
  31. package/docs/continuous-integration.md +0 -22
  32. package/docs/custom-helpers.md +0 -306
  33. package/docs/data.md +0 -379
  34. package/docs/detox.md +0 -235
  35. package/docs/docker.md +0 -136
  36. package/docs/email.md +0 -183
  37. package/docs/examples.md +0 -149
  38. package/docs/helpers/ApiDataFactory.md +0 -266
  39. package/docs/helpers/Appium.md +0 -1374
  40. package/docs/helpers/Detox.md +0 -586
  41. package/docs/helpers/Expect.md +0 -275
  42. package/docs/helpers/FileSystem.md +0 -152
  43. package/docs/helpers/GraphQL.md +0 -151
  44. package/docs/helpers/GraphQLDataFactory.md +0 -226
  45. package/docs/helpers/JSONResponse.md +0 -254
  46. package/docs/helpers/Mochawesome.md +0 -8
  47. package/docs/helpers/MockRequest.md +0 -377
  48. package/docs/helpers/Nightmare.md +0 -1305
  49. package/docs/helpers/OpenAI.md +0 -70
  50. package/docs/helpers/Playwright.md +0 -2759
  51. package/docs/helpers/Polly.md +0 -44
  52. package/docs/helpers/Protractor.md +0 -1769
  53. package/docs/helpers/Puppeteer-firefox.md +0 -86
  54. package/docs/helpers/Puppeteer.md +0 -2317
  55. package/docs/helpers/REST.md +0 -218
  56. package/docs/helpers/TestCafe.md +0 -1321
  57. package/docs/helpers/WebDriver.md +0 -2547
  58. package/docs/hooks.md +0 -340
  59. package/docs/index.md +0 -111
  60. package/docs/installation.md +0 -75
  61. package/docs/internal-api.md +0 -266
  62. package/docs/locators.md +0 -339
  63. package/docs/mobile-react-native-locators.md +0 -67
  64. package/docs/mobile.md +0 -338
  65. package/docs/pageobjects.md +0 -291
  66. package/docs/parallel.md +0 -400
  67. package/docs/playwright.md +0 -632
  68. package/docs/plugins.md +0 -1259
  69. package/docs/puppeteer.md +0 -316
  70. package/docs/quickstart.md +0 -162
  71. package/docs/react.md +0 -70
  72. package/docs/reports.md +0 -392
  73. package/docs/secrets.md +0 -36
  74. package/docs/shadow.md +0 -68
  75. package/docs/shared/keys.mustache +0 -31
  76. package/docs/shared/react.mustache +0 -1
  77. package/docs/testcafe.md +0 -174
  78. package/docs/translation.md +0 -247
  79. package/docs/tutorial.md +0 -271
  80. package/docs/typescript.md +0 -180
  81. package/docs/ui.md +0 -59
  82. package/docs/videos.md +0 -28
  83. package/docs/visual.md +0 -202
  84. package/docs/vue.md +0 -143
  85. package/docs/webapi/amOnPage.mustache +0 -11
  86. package/docs/webapi/appendField.mustache +0 -11
  87. package/docs/webapi/attachFile.mustache +0 -12
  88. package/docs/webapi/blur.mustache +0 -18
  89. package/docs/webapi/checkOption.mustache +0 -13
  90. package/docs/webapi/clearCookie.mustache +0 -9
  91. package/docs/webapi/clearField.mustache +0 -9
  92. package/docs/webapi/click.mustache +0 -25
  93. package/docs/webapi/clickLink.mustache +0 -8
  94. package/docs/webapi/closeCurrentTab.mustache +0 -7
  95. package/docs/webapi/closeOtherTabs.mustache +0 -8
  96. package/docs/webapi/dontSee.mustache +0 -11
  97. package/docs/webapi/dontSeeCheckboxIsChecked.mustache +0 -10
  98. package/docs/webapi/dontSeeCookie.mustache +0 -8
  99. package/docs/webapi/dontSeeCurrentUrlEquals.mustache +0 -10
  100. package/docs/webapi/dontSeeElement.mustache +0 -8
  101. package/docs/webapi/dontSeeElementInDOM.mustache +0 -8
  102. package/docs/webapi/dontSeeInCurrentUrl.mustache +0 -4
  103. package/docs/webapi/dontSeeInField.mustache +0 -11
  104. package/docs/webapi/dontSeeInSource.mustache +0 -8
  105. package/docs/webapi/dontSeeInTitle.mustache +0 -8
  106. package/docs/webapi/doubleClick.mustache +0 -13
  107. package/docs/webapi/downloadFile.mustache +0 -12
  108. package/docs/webapi/dragAndDrop.mustache +0 -9
  109. package/docs/webapi/dragSlider.mustache +0 -11
  110. package/docs/webapi/executeAsyncScript.mustache +0 -24
  111. package/docs/webapi/executeScript.mustache +0 -26
  112. package/docs/webapi/fillField.mustache +0 -16
  113. package/docs/webapi/focus.mustache +0 -13
  114. package/docs/webapi/forceClick.mustache +0 -28
  115. package/docs/webapi/forceRightClick.mustache +0 -18
  116. package/docs/webapi/grabAllWindowHandles.mustache +0 -7
  117. package/docs/webapi/grabAttributeFrom.mustache +0 -10
  118. package/docs/webapi/grabAttributeFromAll.mustache +0 -9
  119. package/docs/webapi/grabBrowserLogs.mustache +0 -9
  120. package/docs/webapi/grabCookie.mustache +0 -11
  121. package/docs/webapi/grabCssPropertyFrom.mustache +0 -11
  122. package/docs/webapi/grabCssPropertyFromAll.mustache +0 -10
  123. package/docs/webapi/grabCurrentUrl.mustache +0 -9
  124. package/docs/webapi/grabCurrentWindowHandle.mustache +0 -6
  125. package/docs/webapi/grabDataFromPerformanceTiming.mustache +0 -20
  126. package/docs/webapi/grabElementBoundingRect.mustache +0 -20
  127. package/docs/webapi/grabGeoLocation.mustache +0 -8
  128. package/docs/webapi/grabHTMLFrom.mustache +0 -10
  129. package/docs/webapi/grabHTMLFromAll.mustache +0 -9
  130. package/docs/webapi/grabNumberOfOpenTabs.mustache +0 -8
  131. package/docs/webapi/grabNumberOfVisibleElements.mustache +0 -9
  132. package/docs/webapi/grabPageScrollPosition.mustache +0 -8
  133. package/docs/webapi/grabPopupText.mustache +0 -5
  134. package/docs/webapi/grabSource.mustache +0 -8
  135. package/docs/webapi/grabTextFrom.mustache +0 -10
  136. package/docs/webapi/grabTextFromAll.mustache +0 -9
  137. package/docs/webapi/grabTitle.mustache +0 -8
  138. package/docs/webapi/grabValueFrom.mustache +0 -9
  139. package/docs/webapi/grabValueFromAll.mustache +0 -8
  140. package/docs/webapi/grabWebElement.mustache +0 -9
  141. package/docs/webapi/grabWebElements.mustache +0 -9
  142. package/docs/webapi/moveCursorTo.mustache +0 -12
  143. package/docs/webapi/openNewTab.mustache +0 -7
  144. package/docs/webapi/pressKey.mustache +0 -12
  145. package/docs/webapi/pressKeyDown.mustache +0 -12
  146. package/docs/webapi/pressKeyUp.mustache +0 -12
  147. package/docs/webapi/pressKeyWithKeyNormalization.mustache +0 -60
  148. package/docs/webapi/refreshPage.mustache +0 -6
  149. package/docs/webapi/resizeWindow.mustache +0 -6
  150. package/docs/webapi/rightClick.mustache +0 -14
  151. package/docs/webapi/saveElementScreenshot.mustache +0 -10
  152. package/docs/webapi/saveScreenshot.mustache +0 -12
  153. package/docs/webapi/say.mustache +0 -10
  154. package/docs/webapi/scrollIntoView.mustache +0 -11
  155. package/docs/webapi/scrollPageToBottom.mustache +0 -6
  156. package/docs/webapi/scrollPageToTop.mustache +0 -6
  157. package/docs/webapi/scrollTo.mustache +0 -12
  158. package/docs/webapi/see.mustache +0 -11
  159. package/docs/webapi/seeAttributesOnElements.mustache +0 -9
  160. package/docs/webapi/seeCheckboxIsChecked.mustache +0 -10
  161. package/docs/webapi/seeCookie.mustache +0 -8
  162. package/docs/webapi/seeCssPropertiesOnElements.mustache +0 -9
  163. package/docs/webapi/seeCurrentUrlEquals.mustache +0 -11
  164. package/docs/webapi/seeElement.mustache +0 -8
  165. package/docs/webapi/seeElementInDOM.mustache +0 -8
  166. package/docs/webapi/seeInCurrentUrl.mustache +0 -8
  167. package/docs/webapi/seeInField.mustache +0 -12
  168. package/docs/webapi/seeInPopup.mustache +0 -8
  169. package/docs/webapi/seeInSource.mustache +0 -7
  170. package/docs/webapi/seeInTitle.mustache +0 -8
  171. package/docs/webapi/seeNumberOfElements.mustache +0 -11
  172. package/docs/webapi/seeNumberOfVisibleElements.mustache +0 -10
  173. package/docs/webapi/seeTextEquals.mustache +0 -9
  174. package/docs/webapi/seeTitleEquals.mustache +0 -8
  175. package/docs/webapi/selectOption.mustache +0 -21
  176. package/docs/webapi/setCookie.mustache +0 -16
  177. package/docs/webapi/setGeoLocation.mustache +0 -12
  178. package/docs/webapi/switchTo.mustache +0 -9
  179. package/docs/webapi/switchToNextTab.mustache +0 -10
  180. package/docs/webapi/switchToPreviousTab.mustache +0 -10
  181. package/docs/webapi/type.mustache +0 -21
  182. package/docs/webapi/uncheckOption.mustache +0 -13
  183. package/docs/webapi/wait.mustache +0 -8
  184. package/docs/webapi/waitForClickable.mustache +0 -11
  185. package/docs/webapi/waitForDetached.mustache +0 -10
  186. package/docs/webapi/waitForElement.mustache +0 -11
  187. package/docs/webapi/waitForEnabled.mustache +0 -6
  188. package/docs/webapi/waitForFunction.mustache +0 -17
  189. package/docs/webapi/waitForInvisible.mustache +0 -10
  190. package/docs/webapi/waitForNumberOfTabs.mustache +0 -9
  191. package/docs/webapi/waitForText.mustache +0 -13
  192. package/docs/webapi/waitForValue.mustache +0 -10
  193. package/docs/webapi/waitForVisible.mustache +0 -10
  194. package/docs/webapi/waitInUrl.mustache +0 -9
  195. package/docs/webapi/waitNumberOfVisibleElements.mustache +0 -10
  196. package/docs/webapi/waitToHide.mustache +0 -10
  197. package/docs/webapi/waitUrlEquals.mustache +0 -10
  198. package/docs/webdriver.md +0 -701
  199. package/docs/wiki/Books-&-Posts.md +0 -27
  200. package/docs/wiki/Community-Helpers-&-Plugins.md +0 -53
  201. package/docs/wiki/Converting-Playwright-to-Istanbul-Coverage.md +0 -61
  202. package/docs/wiki/Examples.md +0 -145
  203. package/docs/wiki/Google-Summer-of-Code-(GSoC)-2020.md +0 -68
  204. package/docs/wiki/Home.md +0 -16
  205. package/docs/wiki/Migration-to-Appium-v2---CodeceptJS.md +0 -83
  206. package/docs/wiki/Release-Process.md +0 -24
  207. package/docs/wiki/Roadmap.md +0 -23
  208. package/docs/wiki/Tests.md +0 -1393
  209. package/docs/wiki/Upgrading-to-CodeceptJS-3.md +0 -153
  210. package/docs/wiki/Videos.md +0 -19
  211. package/lib/css2xpath/js/css_to_xpath.js +0 -20
  212. package/lib/css2xpath/js/expression.js +0 -23
  213. package/lib/css2xpath/js/renderer.js +0 -239
@@ -1,153 +0,0 @@
1
- 🚀 CodeceptJS 3 is out now. Install it:
2
-
3
- ```
4
- npm i codeceptjs
5
- ```
6
-
7
- * [COMPLETE CHANGELOG](https://github.com/Codeception/CodeceptJS/blob/codeceptjs-v3.0/CHANGELOG.md#300-beta)
8
- * [Documentation](https://github.com/Codeception/CodeceptJS/tree/codeceptjs-v3.0/docs)
9
-
10
- After installing a new version, run `codecept3-upgrade` which is described below:
11
-
12
- ---
13
-
14
- CodeceptJS 3.0 is a new version of CodeceptJS with some breaking changes included.
15
- You should update your project following this guide to ensure that everything works correctly.
16
-
17
- ### 1️⃣ Syntax Change
18
-
19
- CodeceptJS 3.0 introduced a new syntax for declaring tests, instead of:
20
-
21
- ```js
22
- Scenario('title', (I, loginPage) => {})
23
- ```
24
- we use a new way of passing arguments into a test, via destruction:
25
-
26
- ```js
27
- Scenario('title', ({ I, loginPage }) => {})
28
- ```
29
-
30
- This works similarly to `inject()` command. This change was done to unify accessing [dependency injection container](https://codecept.io/pageobjects/#dependency-injection), and to provide better TypeScript support.
31
-
32
- > If you use BDD-style project with Gherkin, no changes needed for this step.
33
-
34
- To upgrade your project, you don't need to change manually all your tests.
35
-
36
- 💪 **Use [codecept3-upgrade tool](https://www.npmjs.com/package/codecept3-upgrade) to perform the migration**. Use it carefully, as it updates your current code.
37
-
38
- To upgrade your codebase, commit all your changes, and switch to a new branch.
39
- Run upgrade script (even without installing) for a directory where you have your tests:
40
-
41
- ```
42
- npx codecept3-upgrade tests
43
- ```
44
- Review the changes in Git Diff and try to execute tests using CodeceptJS 3.0
45
-
46
-
47
- ### 2️⃣ Grabbers signature change
48
-
49
- There were confusion and inconsistency across grab* methods. What they will return if multiple elements are found? A single element or an array? This was the problem as the format was dependent on a page content.
50
-
51
- In 3.0 we decided to make all current grab* methods to return a single value only. While we add new methods grab**FromAll that return an array.
52
-
53
- For instance, `grabTextFrom` will always return a single text value, while `grabTextFromAll` will return an array of values:
54
-
55
- ```js
56
- await I.grabTextFrom('.username'); => 'john'
57
- await I.grabTextFromAll('.username'); => ['john', 'claudia', 'bill']
58
- ```
59
-
60
- Please update parts in your project where you rely on grab* methods to return an array.
61
-
62
-
63
- | Single Value | Multiple Values |
64
- | -- | -- |
65
- | ✋`grabTextFrom` | 🙌 `grabTextFromAll` |
66
- | ✋`grabValueFrom` | 🙌 `grabValueFromAll` |
67
- | ✋ `grabAttributeFrom` | 🙌`grabAttributeFromAll` |
68
- | ✋ `grabHTMLFrom` | 🙌 `grabHTMLFromAll` |
69
- | ✋ `grabCssPropertyFrom` | 🙌 `grabCssPropertyFromAll` |
70
-
71
- > Single-value `grab*From` will throw error when no data was matched, while `grab*FromAll` will return array.
72
-
73
- ### 3️⃣ Bootstrap / Teardown Changed
74
-
75
- `async/await` paradigm changed the way we write asynchronous code in NodeJS.
76
- However, bootstrap functions were created to use old-style methods of passing `done` callback inside.
77
-
78
- In 3.0 we decided to completely change the way async bootstrap is performed and replace all it with async/await functions:
79
-
80
- ```js
81
- // before
82
- bootstrap: (done) => {
83
- server.start().then(done);
84
- },
85
-
86
- // after
87
- bootstrap: async () => {
88
- await server.start();
89
- }
90
- ```
91
- Passing a string as bootstrap function (to require a function from external file) is also not supported:
92
-
93
- ```js
94
- // before
95
- bootstrap: './server_start.js',
96
-
97
- // after
98
- bootstrap: require('./server_start.js'),
99
- ```
100
-
101
- The same rules are applied to teardown, bootstrapAll, teardownAll.
102
-
103
- ### 4️⃣ Locator Detection Heuristic Change
104
-
105
- In 3.0 we added a new rule to auto-detect CSS locator. If a locator starts with `[` parser will use it as a CSS locator, without trying to match value by text.
106
-
107
- * Previous behavior: I.click('[user]') - will try to search for a link with `[user]` text, if no found - take `[user]` as CSS locator
108
- * Current behavior: I.click('[user]') - will check only for CSS locator `[user]`
109
-
110
- ### 5️⃣ Improved Parallel Execution with Workers
111
-
112
- CodeceptJS has two parallel execution modes:
113
-
114
- * classical `run-multiple` which spawns independent CodeceptJS processes on system level.
115
- * threaded `run-workers` which uses NodeJS workers instead of subprocesses.
116
-
117
- Workers are faster, they can communicate with parent thread. Unfortunately, `run-workers` was not as efficient as `run-multiple` because there was no way of declaring sophisticated configs for parallel execution. For instance, running tests in 4 threads in 2 browsers could not be set.
118
-
119
- We updated workers API to make them as flexible as possible. You don't even need to put complex logic into config! You can create your own parallel runner and customize it to match your expectations:
120
-
121
- ```js
122
- // don't initialize workers in constructor
123
- const workers = new Workers(null, workerConfig);
124
- // split tests by suites in 2 groups
125
- const testGroups = workers.createGroupsOfSuites(2);
126
-
127
- const browsers = ['firefox', 'chrome'];
128
-
129
- const configs = browsers.map(browser => {
130
- return helpers: {
131
- WebDriver: { browser }
132
- }
133
- });
134
-
135
- for (const config of configs) {
136
- for (group of groupOfTests) {
137
- const worker = workers.spawn();
138
- worker.addTests(group);
139
- worker.addConfig(config);
140
- }
141
- }
142
-
143
- workers.run();
144
- ```
145
- [Learn more about how you can create a parallel runner](https://github.com/Codeception/CodeceptJS/blob/codeceptjs-v3.0/docs/parallel.md#custom-parallel-execution).
146
-
147
- `run-multiple` will still work but it is considered deprecated and won't be supported.
148
-
149
- ### WebDriverIO helper removed
150
-
151
- WebDriverIO helper supported webdriverio v4 library, which is not maintained anymore. It should be easy to switch to WebDriver helper which supports webdriverio v6.
152
-
153
-
@@ -1,19 +0,0 @@
1
- [![](http://i3.ytimg.com/vi/BRMWstiOTks/maxresdefault.jpg)](https://www.youtube.com/watch?v=BRMWstiOTks)
2
-
3
- ## [An Introduction, Getting started and working with CodeceptJS & Puppeteer (EAWeekend)](https://www.youtube.com/watch?v=BRMWstiOTks)
4
-
5
- ## [CodeceptJS Official YouTube Channel](https://www.youtube.com/channel/UCEs4030bmtonyDhTHEXa_2g)
6
-
7
- ## [Introductory Videos](https://www.youtube.com/watch?v=FPFG1rBNJ64&list=PLcFXthgti9Lt4SjSvL1ALDg6dOeTC0TvT)
8
-
9
- Free educational videos provided by our community member **[@ontytoom](http://github.com/ontytoom)**.
10
-
11
- 1. [Installation](https://www.youtube.com/watch?v=FPFG1rBNJ64)
12
- 1. [Creating a Test](https://www.youtube.com/watch?v=mdQZjL3h9d0)
13
- 1. [Using Page Objects](https://www.youtube.com/watch?v=s677_6VctjQ)
14
-
15
- ## [Practical E2E Testing with CodeceptJS](https://www.udemy.com/practical-e2e-testing-with-codeceptjs/)
16
-
17
- Udemy course by Luke Beilharz
18
-
19
-
@@ -1,20 +0,0 @@
1
- (function() {
2
- var self = this;
3
- var parser, xpathBuilder, Expression, parse, convertToXpath;
4
- parser = require("bo-selector").parser;
5
- xpathBuilder = require("xpath-builder").dsl();
6
- Expression = require("./expression");
7
- parser.yy.create = function(data) {
8
- var self = this;
9
- return new Expression(data);
10
- };
11
- parse = function(selector) {
12
- return parser.parse(selector).render(xpathBuilder, "descendant");
13
- };
14
- convertToXpath = function(selector) {
15
- return parse(selector).toXPath();
16
- };
17
- convertToXpath.parse = parse;
18
- convertToXpath.xPathBuilder = xpathBuilder;
19
- module.exports = convertToXpath;
20
- }).call(this);
@@ -1,23 +0,0 @@
1
- (function() {
2
- var self = this;
3
- var Renderer, Expression, extend;
4
- Renderer = require("./renderer");
5
- Expression = function(data) {
6
- extend(this, data);
7
- return this;
8
- };
9
- Expression.prototype.render = function(xpath, combinator) {
10
- var self = this;
11
- return new Renderer().render(self, xpath, combinator);
12
- };
13
- extend = function(o, d) {
14
- var k;
15
- for (k in d) {
16
- (function(k) {
17
- o[k] = d[k];
18
- })(k);
19
- }
20
- return void 0;
21
- };
22
- module.exports = Expression;
23
- }).call(this);
@@ -1,239 +0,0 @@
1
- (function() {
2
- var self = this;
3
- var xpathBuilder, Renderer;
4
- xpathBuilder = require("xpath-builder").dsl();
5
- Renderer = function() {
6
- return this;
7
- };
8
- Renderer.prototype = {
9
- render: function(node, xpath, combinator) {
10
- var self = this;
11
- var fn;
12
- fn = self[node.type];
13
- if (!fn) {
14
- throw new Error("No renderer for '" + node.type + "'");
15
- }
16
- return fn.call(self, node, xpath, combinator);
17
- },
18
- selector_list: function(node, xpath, combinator) {
19
- var self = this;
20
- var x, i;
21
- x = self.render(node.selectors[0], xpath, combinator);
22
- for (i = 1; i < node.selectors.length; ++i) {
23
- x = x.union(self.render(node.selectors[i], xpath, combinator));
24
- }
25
- return x;
26
- },
27
- constraint_list: function(node, xpath, combinator) {
28
- var self = this;
29
- return self.element(node, xpath, combinator);
30
- },
31
- element: function(node, xpath, combinator) {
32
- var self = this;
33
- return self.applyConstraints(node, xpath[combinator].call(xpath, node.name || "*"));
34
- },
35
- combinator_selector: function(node, xpath, combinator) {
36
- var self = this;
37
- var left;
38
- left = self.render(node.left, xpath, combinator);
39
- return self.render(node.right, left, node.combinator);
40
- },
41
- immediate_child: function(node, xpath) {
42
- var self = this;
43
- return self.render(node.child, xpath, "child");
44
- },
45
- pseudo_func: function(node, xpath) {
46
- var self = this;
47
- var fn;
48
- fn = self[node.func.name.replace(/-/g, "_")];
49
- if (fn) {
50
- return fn.call(self, node, xpath);
51
- } else {
52
- throw new Error("Unsupported pseudo function :" + node.func.name + "()");
53
- }
54
- },
55
- pseudo_class: function(node, xpath) {
56
- var self = this;
57
- var fn;
58
- fn = self[node.name.replace(/-/g, "_")];
59
- if (fn) {
60
- return fn.call(self, node, xpath);
61
- } else {
62
- throw new Error("Unsupported pseudo class :" + node.name);
63
- }
64
- },
65
- has: function(node, xpath) {
66
- var self = this;
67
- return self.render(node.func.args, xpathBuilder, "descendant");
68
- },
69
- not: function(node, xpath) {
70
- var self = this;
71
- var firstChild, childType;
72
- firstChild = node.func.args.selectors[0];
73
- childType = firstChild.type;
74
- if (childType === "constraint_list") {
75
- return self.combineConstraints(firstChild, xpath).inverse();
76
- } else {
77
- return self.matchesSelectorList(node.func.args, xpath).inverse();
78
- }
79
- },
80
- nth_child: function(node, xpath) {
81
- var self = this;
82
- return xpath.nthChild(Number(node.func.args));
83
- },
84
- first_child: function(node, xpath) {
85
- var self = this;
86
- return xpath.firstChild();
87
- },
88
- last_child: function(node, xpath) {
89
- var self = this;
90
- return xpath.lastChild();
91
- },
92
- nth_last_child: function(node, xpath) {
93
- var self = this;
94
- return xpath.nthLastChild(Number(node.func.args));
95
- },
96
- only_child: function(node, xpath) {
97
- var self = this;
98
- return xpath.onlyChild();
99
- },
100
- only_of_type: function(node, xpath) {
101
- var self = this;
102
- return xpath.onlyOfType();
103
- },
104
- nth_of_type: function(node, xpath) {
105
- var self = this;
106
- var type;
107
- type = node.func.args.type;
108
- if (type === "odd") {
109
- return xpath.nthOfTypeOdd();
110
- } else if (type === "even") {
111
- return xpath.nthOfTypeEven();
112
- } else if (type === "an") {
113
- return xpath.nthOfTypeMod(Number(node.func.args.a));
114
- } else if (type === "n_plus_b") {
115
- return xpath.nthOfTypeMod(1, Number(node.func.args.b));
116
- } else if (type === "an_plus_b") {
117
- return xpath.nthOfTypeMod(Number(node.func.args.a), Number(node.func.args.b));
118
- } else {
119
- return xpath.nthOfType(Number(node.func.args));
120
- }
121
- },
122
- nth_last_of_type: function(node, xpath) {
123
- var self = this;
124
- var type;
125
- type = node.func.args.type;
126
- if (type === "odd") {
127
- return xpath.nthLastOfTypeOdd();
128
- } else if (type === "even") {
129
- return xpath.nthLastOfTypeEven();
130
- } else if (type === "an") {
131
- return xpath.nthLastOfTypeMod(Number(node.func.args.a));
132
- } else if (type === "n_plus_b") {
133
- return xpath.nthLastOfTypeMod(1, Number(node.func.args.b));
134
- } else if (type === "an_plus_b") {
135
- return xpath.nthLastOfTypeMod(Number(node.func.args.a), Number(node.func.args.b));
136
- } else {
137
- return xpath.nthLastOfType(Number(node.func.args));
138
- }
139
- },
140
- last_of_type: function(node, xpath) {
141
- var self = this;
142
- return xpath.lastOfType();
143
- },
144
- empty: function(node, xpath) {
145
- var self = this;
146
- return xpath.empty();
147
- },
148
- has_attribute: function(node, xpath) {
149
- var self = this;
150
- return xpathBuilder.attr(node.name);
151
- },
152
- attribute_equals: function(node, xpath) {
153
- var self = this;
154
- return xpathBuilder.attr(node.name).equals(node.value);
155
- },
156
- attribute_contains: function(node, xpath) {
157
- var self = this;
158
- return xpathBuilder.attr(node.name).contains(node.value);
159
- },
160
- attribute_contains_word: function(node, xpath) {
161
- var self = this;
162
- return xpath.concat(" ", xpathBuilder.attr(node.name).normalize(), " ").contains(" " + node.value + " ");
163
- },
164
- attribute_contains_prefix: function(node) {
165
- var self = this;
166
- return xpathBuilder.attr(node.name).startsWith(node.value).or(xpathBuilder.attr(node.name).startsWith(node.value + "-"));
167
- },
168
- attribute_starts_with: function(node, xpath) {
169
- var self = this;
170
- return xpathBuilder.attr(node.name).startsWith(node.value);
171
- },
172
- attribute_ends_with: function(node) {
173
- var self = this;
174
- return xpathBuilder.attr(node.name).endsWith(node.value);
175
- },
176
- "class": function(node) {
177
- var self = this;
178
- return self.attribute_contains_word({
179
- name: "class",
180
- value: node.name
181
- }, xpathBuilder);
182
- },
183
- id: function(node) {
184
- var self = this;
185
- return xpathBuilder.attr("id").equals(node.name);
186
- },
187
- previous_sibling: function(node, xpath, combinator) {
188
- var self = this;
189
- var left;
190
- left = self.render(node.left, xpath, combinator);
191
- return self.applyConstraints(node.right, left.axis("following-sibling", node.right.name));
192
- },
193
- adjacent_sibling: function(node, xpath, combinator) {
194
- var self = this;
195
- var left;
196
- left = self.render(node.left, xpath, combinator);
197
- return self.applyConstraints(node.right, left.axis("following-sibling::*[1]/self", node.right.name));
198
- },
199
- first_of_type: function(node, xpath) {
200
- var self = this;
201
- return xpath.firstOfType();
202
- },
203
- matchesSelectorList: function(node, xpath) {
204
- var self = this;
205
- var condition, i;
206
- if (node.selectors.length > 0) {
207
- condition = self.matchesSelector(node.selectors[0], xpathBuilder);
208
- for (i = 1; i < node.selectors.length; ++i) {
209
- condition = condition.or(self.matchesSelector(node.selectors[i], xpathBuilder));
210
- }
211
- return condition;
212
- } else {
213
- return xpath;
214
- }
215
- },
216
- matchesSelector: function(node, xpath) {
217
- var self = this;
218
- return xpath.name().equals(node.name);
219
- },
220
- combineConstraints: function(node, xpath) {
221
- var self = this;
222
- var condition, i;
223
- condition = self.render(node.constraints[0], xpath);
224
- for (i = 1; i < node.constraints.length; ++i) {
225
- condition = condition.and(self.render(node.constraints[i], condition));
226
- }
227
- return condition;
228
- },
229
- applyConstraints: function(node, xpath) {
230
- var self = this;
231
- if (node.constraints.length > 0) {
232
- return xpath.where(self.combineConstraints(node, xpath));
233
- } else {
234
- return xpath;
235
- }
236
- }
237
- };
238
- module.exports = Renderer;
239
- }).call(this);